@soulcraft/sdk 1.0.0 → 1.2.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/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/auth/service-token.d.ts +62 -0
- package/dist/modules/auth/service-token.d.ts.map +1 -0
- package/dist/modules/auth/service-token.js +99 -0
- package/dist/modules/auth/service-token.js.map +1 -0
- package/dist/modules/billing/firestore-provider.d.ts +60 -0
- package/dist/modules/billing/firestore-provider.d.ts.map +1 -0
- package/dist/modules/billing/firestore-provider.js +314 -0
- package/dist/modules/billing/firestore-provider.js.map +1 -0
- package/dist/modules/billing/index.d.ts +58 -0
- package/dist/modules/billing/index.d.ts.map +1 -0
- package/dist/modules/billing/index.js +164 -0
- package/dist/modules/billing/index.js.map +1 -0
- package/dist/modules/billing/local-provider.d.ts +38 -0
- package/dist/modules/billing/local-provider.d.ts.map +1 -0
- package/dist/modules/billing/local-provider.js +242 -0
- package/dist/modules/billing/local-provider.js.map +1 -0
- package/dist/modules/billing/portal-provider.d.ts +70 -0
- package/dist/modules/billing/portal-provider.d.ts.map +1 -0
- package/dist/modules/billing/portal-provider.js +204 -0
- package/dist/modules/billing/portal-provider.js.map +1 -0
- package/dist/modules/billing/types.d.ts +323 -3
- package/dist/modules/billing/types.d.ts.map +1 -1
- package/dist/modules/billing/types.js +22 -2
- package/dist/modules/billing/types.js.map +1 -1
- package/dist/modules/billing/usage-buffer.d.ts +72 -0
- package/dist/modules/billing/usage-buffer.d.ts.map +1 -0
- package/dist/modules/billing/usage-buffer.js +141 -0
- package/dist/modules/billing/usage-buffer.js.map +1 -0
- package/dist/modules/formats/types.d.ts +65 -3
- package/dist/modules/formats/types.d.ts.map +1 -1
- package/dist/modules/formats/types.js +40 -3
- package/dist/modules/formats/types.js.map +1 -1
- package/dist/modules/formats/wdoc.d.ts +263 -0
- package/dist/modules/formats/wdoc.d.ts.map +1 -0
- package/dist/modules/formats/wdoc.js +21 -0
- package/dist/modules/formats/wdoc.js.map +1 -0
- package/dist/modules/formats/wquiz.d.ts +122 -0
- package/dist/modules/formats/wquiz.d.ts.map +1 -0
- package/dist/modules/formats/wquiz.js +23 -0
- package/dist/modules/formats/wquiz.js.map +1 -0
- package/dist/modules/formats/wslide.d.ts +130 -0
- package/dist/modules/formats/wslide.d.ts.map +1 -0
- package/dist/modules/formats/wslide.js +23 -0
- package/dist/modules/formats/wslide.js.map +1 -0
- package/dist/modules/formats/wviz.d.ts +114 -0
- package/dist/modules/formats/wviz.d.ts.map +1 -0
- package/dist/modules/formats/wviz.js +21 -0
- package/dist/modules/formats/wviz.js.map +1 -0
- package/dist/modules/hall/browser.d.ts +88 -0
- package/dist/modules/hall/browser.d.ts.map +1 -0
- package/dist/modules/hall/browser.js +265 -0
- package/dist/modules/hall/browser.js.map +1 -0
- package/dist/modules/hall/protocol.d.ts +39 -0
- package/dist/modules/hall/protocol.d.ts.map +1 -0
- package/dist/modules/hall/protocol.js +52 -0
- package/dist/modules/hall/protocol.js.map +1 -0
- package/dist/modules/hall/server.d.ts +172 -0
- package/dist/modules/hall/server.d.ts.map +1 -0
- package/dist/modules/hall/server.js +457 -0
- package/dist/modules/hall/server.js.map +1 -0
- package/dist/modules/hall/types.d.ts +502 -31
- package/dist/modules/hall/types.d.ts.map +1 -1
- package/dist/modules/hall/types.js +13 -8
- package/dist/modules/hall/types.js.map +1 -1
- package/dist/modules/kits/index.d.ts +41 -0
- package/dist/modules/kits/index.d.ts.map +1 -0
- package/dist/modules/kits/index.js +85 -0
- package/dist/modules/kits/index.js.map +1 -0
- package/dist/modules/kits/types.d.ts +107 -3
- package/dist/modules/kits/types.d.ts.map +1 -1
- package/dist/modules/kits/types.js +15 -2
- package/dist/modules/kits/types.js.map +1 -1
- package/dist/modules/license/index.d.ts +53 -0
- package/dist/modules/license/index.d.ts.map +1 -0
- package/dist/modules/license/index.js +233 -0
- package/dist/modules/license/index.js.map +1 -0
- package/dist/modules/license/types.d.ts +222 -3
- package/dist/modules/license/types.d.ts.map +1 -1
- package/dist/modules/license/types.js +21 -2
- package/dist/modules/license/types.js.map +1 -1
- package/dist/modules/notifications/index.d.ts +40 -0
- package/dist/modules/notifications/index.d.ts.map +1 -0
- package/dist/modules/notifications/index.js +280 -0
- package/dist/modules/notifications/index.js.map +1 -0
- package/dist/modules/notifications/types.d.ts +152 -3
- package/dist/modules/notifications/types.d.ts.map +1 -1
- package/dist/modules/notifications/types.js +21 -2
- package/dist/modules/notifications/types.js.map +1 -1
- package/dist/server/create-sdk.d.ts +4 -0
- package/dist/server/create-sdk.d.ts.map +1 -1
- package/dist/server/create-sdk.js +19 -26
- package/dist/server/create-sdk.js.map +1 -1
- package/dist/server/hall-handlers.d.ts +90 -151
- package/dist/server/hall-handlers.d.ts.map +1 -1
- package/dist/server/hall-handlers.js +84 -204
- package/dist/server/hall-handlers.js.map +1 -1
- package/dist/server/index.d.ts +10 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +9 -2
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +35 -25
- package/dist/types.d.ts.map +1 -1
- package/docs/USAGE.md +224 -1
- package/package.json +13 -5
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/browser
|
|
3
|
+
* @description Browser-side Hall room client — joins a WebRTC room via a session token.
|
|
4
|
+
*
|
|
5
|
+
* `joinHallRoom` is the browser entry point for Hall real-time communication.
|
|
6
|
+
* It opens a WebSocket to the Hall signaling endpoint, negotiates a WebRTC peer
|
|
7
|
+
* connection via offer/answer/ICE, and returns a `HallRoomHandle` with typed events
|
|
8
|
+
* for tracks, transcripts, concept mentions, and room lifecycle.
|
|
9
|
+
*
|
|
10
|
+
* **Auth model:** The browser never sees the product's shared secret. The product
|
|
11
|
+
* backend mints a short-lived HMAC session token (via `sdk.hall.createSessionToken`)
|
|
12
|
+
* and passes it to the browser. The browser passes the token to `joinHallRoom` — that
|
|
13
|
+
* is the only browser credential.
|
|
14
|
+
*
|
|
15
|
+
* This module has no server-only dependencies and is safe to bundle for the browser.
|
|
16
|
+
* It does require `RTCPeerConnection` and `WebSocket` to be available (standard in
|
|
17
|
+
* all modern browsers; not available in Node.js without polyfills).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { joinHallRoom } from '@soulcraft/sdk/client'
|
|
22
|
+
*
|
|
23
|
+
* // 1. Get token from product backend:
|
|
24
|
+
* const { token, hallUrl } = await fetch('/api/session/join').then(r => r.json())
|
|
25
|
+
*
|
|
26
|
+
* // 2. Get camera + mic:
|
|
27
|
+
* const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
|
28
|
+
*
|
|
29
|
+
* // 3. Join room:
|
|
30
|
+
* const room = await joinHallRoom({ token, hallUrl })
|
|
31
|
+
* room.addStream(stream)
|
|
32
|
+
*
|
|
33
|
+
* // 4. Handle events:
|
|
34
|
+
* room.on('trackAdded', ({ peerId, streams }) => {
|
|
35
|
+
* document.getElementById(`video-${peerId}`).srcObject = streams[0]
|
|
36
|
+
* })
|
|
37
|
+
* room.on('transcript', ({ peerId, text, isFinal }) => {
|
|
38
|
+
* if (isFinal) appendCaption(peerId, text)
|
|
39
|
+
* })
|
|
40
|
+
* room.on('conceptMention', ({ nodeId, confidence }) => pulseGraphNode(nodeId, confidence))
|
|
41
|
+
*
|
|
42
|
+
* // 5. On leave:
|
|
43
|
+
* room.close()
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
class HallRoomHandleImpl {
|
|
47
|
+
roomId;
|
|
48
|
+
peerId;
|
|
49
|
+
#listeners = {
|
|
50
|
+
transcript: new Set(),
|
|
51
|
+
conceptMention: new Set(),
|
|
52
|
+
relationProposed: new Set(),
|
|
53
|
+
speakerChanged: new Set(),
|
|
54
|
+
peerJoined: new Set(),
|
|
55
|
+
peerLeft: new Set(),
|
|
56
|
+
trackAdded: new Set(),
|
|
57
|
+
trackRemoved: new Set(),
|
|
58
|
+
closed: new Set(),
|
|
59
|
+
error: new Set(),
|
|
60
|
+
};
|
|
61
|
+
#pc;
|
|
62
|
+
#ws;
|
|
63
|
+
constructor(roomId, peerId, pc, ws) {
|
|
64
|
+
this.roomId = roomId;
|
|
65
|
+
this.peerId = peerId;
|
|
66
|
+
this.#pc = pc;
|
|
67
|
+
this.#ws = ws;
|
|
68
|
+
}
|
|
69
|
+
on(event, listener) {
|
|
70
|
+
;
|
|
71
|
+
this.#listeners[event].add(listener);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
off(event, listener) {
|
|
75
|
+
;
|
|
76
|
+
this.#listeners[event].delete(listener);
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
addStream(stream) {
|
|
80
|
+
for (const track of stream.getTracks()) {
|
|
81
|
+
this.#pc.addTrack(track, stream);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
close() {
|
|
85
|
+
this.#ws.close(1000, 'peer leaving');
|
|
86
|
+
this.#pc.close();
|
|
87
|
+
}
|
|
88
|
+
/** @internal */
|
|
89
|
+
_dispatch(event, payload) {
|
|
90
|
+
for (const listener of this.#listeners[event]) {
|
|
91
|
+
try {
|
|
92
|
+
listener(payload);
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
console.error(`[Hall] uncaught error in room '${this.roomId}' ${event} listener:`, e);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// ─── joinHallRoom ─────────────────────────────────────────────────────────────
|
|
101
|
+
/**
|
|
102
|
+
* Join a Hall room from the browser using a session token.
|
|
103
|
+
*
|
|
104
|
+
* Opens a WebSocket to `{hallUrl}/ws/session/{token}`, creates an `RTCPeerConnection`,
|
|
105
|
+
* performs the offer/answer/ICE exchange, and resolves once the peer connection reaches
|
|
106
|
+
* `connected` state. Returns a {@link HallRoomHandle} with typed events.
|
|
107
|
+
*
|
|
108
|
+
* @param options - Token, Hall URL, and optional ICE server overrides.
|
|
109
|
+
* @returns A connected `HallRoomHandle`.
|
|
110
|
+
* @throws {Error} If the signaling handshake fails or the connection times out.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const room = await joinHallRoom({ token, hallUrl: 'wss://hall.soulcraft.com' })
|
|
115
|
+
* room.addStream(localStream)
|
|
116
|
+
* room.on('trackAdded', ({ peerId, streams }) => renderVideo(peerId, streams[0]))
|
|
117
|
+
* room.on('transcript', ({ text, isFinal }) => { if (isFinal) showCaption(text) })
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export async function joinHallRoom(options) {
|
|
121
|
+
const { token, hallUrl, iceServers = [] } = options;
|
|
122
|
+
const signalingUrl = `${hallUrl}/ws/session/${encodeURIComponent(token)}`;
|
|
123
|
+
// The Hall server sends TURN credentials in the first message after the WebSocket opens.
|
|
124
|
+
// We resolve ICE servers from that before creating the RTCPeerConnection.
|
|
125
|
+
const ws = new WebSocket(signalingUrl);
|
|
126
|
+
const handle = await new Promise((resolve, reject) => {
|
|
127
|
+
const timeout = setTimeout(() => {
|
|
128
|
+
ws.close();
|
|
129
|
+
reject(new Error('Hall: signaling connection timed out after 30s'));
|
|
130
|
+
}, 30_000);
|
|
131
|
+
ws.onerror = () => {
|
|
132
|
+
clearTimeout(timeout);
|
|
133
|
+
reject(new Error('Hall: WebSocket error during signaling'));
|
|
134
|
+
};
|
|
135
|
+
ws.onopen = async () => {
|
|
136
|
+
// Create the peer connection. Hall's TURN server handles NAT traversal —
|
|
137
|
+
// the signaling 'answer' message from Hall includes ICE candidates.
|
|
138
|
+
const pc = new RTCPeerConnection({
|
|
139
|
+
iceServers: [
|
|
140
|
+
// Hall's in-process TURN is always available.
|
|
141
|
+
// The session token encodes the TURN credentials — Hall provides them via the ws.
|
|
142
|
+
{ urls: `${hallUrl.replace('wss://', 'turn:').replace('ws://', 'turn:')}:3478` },
|
|
143
|
+
...iceServers,
|
|
144
|
+
],
|
|
145
|
+
});
|
|
146
|
+
// Send ICE candidates to Hall as they are gathered.
|
|
147
|
+
pc.onicecandidate = (ev) => {
|
|
148
|
+
if (ev.candidate) {
|
|
149
|
+
ws.send(JSON.stringify({ type: 'ice', candidate: JSON.stringify(ev.candidate) }));
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
// Create and send SDP offer.
|
|
153
|
+
const offer = await pc.createOffer();
|
|
154
|
+
await pc.setLocalDescription(offer);
|
|
155
|
+
ws.send(JSON.stringify({ type: 'offer', sdp: offer.sdp }));
|
|
156
|
+
ws.onmessage = async (ev) => {
|
|
157
|
+
let msg;
|
|
158
|
+
try {
|
|
159
|
+
msg = JSON.parse(ev.data);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (msg.type === 'answer') {
|
|
165
|
+
await pc.setRemoteDescription({ type: 'answer', sdp: msg.sdp });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (msg.type === 'ice') {
|
|
169
|
+
try {
|
|
170
|
+
await pc.addIceCandidate(JSON.parse(msg.candidate));
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// Stale ICE candidates are harmless to ignore.
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (msg.type === 'error') {
|
|
178
|
+
clearTimeout(timeout);
|
|
179
|
+
ws.close();
|
|
180
|
+
pc.close();
|
|
181
|
+
reject(new Error(`Hall signaling error: ${msg.message}`));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// The peer connection is considered "ready" once we have a remote description.
|
|
185
|
+
// Resolve the handle at this point so event listeners can be attached.
|
|
186
|
+
// We defer the roomId/peerId extraction to after the connection resolves.
|
|
187
|
+
// Hall sends peerJoined as the first room event after ICE completes.
|
|
188
|
+
if (!roomHandleRef)
|
|
189
|
+
return;
|
|
190
|
+
routeSignalingEvent(roomHandleRef, msg);
|
|
191
|
+
};
|
|
192
|
+
// Resolve once connected. Track events before connection is established are
|
|
193
|
+
// buffered by the browser's RTCPeerConnection — addTrack after setRemoteDescription.
|
|
194
|
+
pc.onconnectionstatechange = () => {
|
|
195
|
+
if (pc.connectionState === 'connected' && !roomHandleRef) {
|
|
196
|
+
// roomId and peerId are decoded from the token by Hall and sent in peerJoined.
|
|
197
|
+
// We use placeholders here; they are filled in by the first peerJoined event.
|
|
198
|
+
const h = new HallRoomHandleImpl('', '', pc, ws);
|
|
199
|
+
roomHandleRef = h;
|
|
200
|
+
clearTimeout(timeout);
|
|
201
|
+
resolve(h);
|
|
202
|
+
}
|
|
203
|
+
if (pc.connectionState === 'failed' || pc.connectionState === 'closed') {
|
|
204
|
+
if (!roomHandleRef) {
|
|
205
|
+
clearTimeout(timeout);
|
|
206
|
+
reject(new Error(`Hall: WebRTC connection ${pc.connectionState}`));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
// Wire track events.
|
|
211
|
+
pc.ontrack = (ev) => {
|
|
212
|
+
if (!roomHandleRef)
|
|
213
|
+
return;
|
|
214
|
+
roomHandleRef._dispatch('trackAdded', {
|
|
215
|
+
peerId: 'remote', // refined by peerJoined
|
|
216
|
+
track: ev.track,
|
|
217
|
+
streams: ev.streams,
|
|
218
|
+
});
|
|
219
|
+
ev.track.onended = () => {
|
|
220
|
+
roomHandleRef?._dispatch('trackRemoved', { peerId: 'remote', track: ev.track });
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
let roomHandleRef = null;
|
|
225
|
+
ws.onclose = (ev) => {
|
|
226
|
+
if (roomHandleRef) {
|
|
227
|
+
if (ev.code !== 1000) {
|
|
228
|
+
roomHandleRef._dispatch('error', { message: `Hall WebSocket closed: ${ev.reason || ev.code}` });
|
|
229
|
+
}
|
|
230
|
+
roomHandleRef._dispatch('closed', { roomId: roomHandleRef.roomId });
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
return handle;
|
|
235
|
+
}
|
|
236
|
+
// ─── Signaling event router ───────────────────────────────────────────────────
|
|
237
|
+
function routeSignalingEvent(handle, msg) {
|
|
238
|
+
switch (msg.type) {
|
|
239
|
+
case 'transcript':
|
|
240
|
+
handle._dispatch('transcript', msg);
|
|
241
|
+
break;
|
|
242
|
+
case 'conceptMention':
|
|
243
|
+
handle._dispatch('conceptMention', msg);
|
|
244
|
+
break;
|
|
245
|
+
case 'relationProposed':
|
|
246
|
+
handle._dispatch('relationProposed', msg);
|
|
247
|
+
break;
|
|
248
|
+
case 'speaker_changed':
|
|
249
|
+
handle._dispatch('speakerChanged', { roomId: msg.roomId, peerId: msg.speakerId });
|
|
250
|
+
break;
|
|
251
|
+
case 'peerJoined':
|
|
252
|
+
handle._dispatch('peerJoined', msg);
|
|
253
|
+
break;
|
|
254
|
+
case 'peerLeft':
|
|
255
|
+
handle._dispatch('peerLeft', msg);
|
|
256
|
+
break;
|
|
257
|
+
case 'roomClosed':
|
|
258
|
+
handle._dispatch('closed', { roomId: msg.roomId });
|
|
259
|
+
break;
|
|
260
|
+
case 'error':
|
|
261
|
+
handle._dispatch('error', { message: msg.message });
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/modules/hall/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AA4DH,MAAM,kBAAkB;IACb,MAAM,CAAQ;IACd,MAAM,CAAQ;IAEd,UAAU,GAAsB;QACvC,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,cAAc,EAAE,IAAI,GAAG,EAAE;QACzB,gBAAgB,EAAE,IAAI,GAAG,EAAE;QAC3B,cAAc,EAAE,IAAI,GAAG,EAAE;QACzB,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,KAAK,EAAE,IAAI,GAAG,EAAE;KACjB,CAAA;IAEQ,GAAG,CAAmB;IACtB,GAAG,CAAW;IAEvB,YAAY,MAAc,EAAE,MAAc,EAAE,EAAqB,EAAE,EAAa;QAC9E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,GAAG,GAAG,EAAE,CAAA;QACb,IAAI,CAAC,GAAG,GAAG,EAAE,CAAA;IACf,CAAC;IAED,EAAE,CACA,KAAQ,EACR,QAAiD;QAEjD,CAAC;QAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAkD,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACvF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,GAAG,CACD,KAAQ,EACR,QAAiD;QAEjD,CAAC;QAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAkD,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC1F,OAAO,IAAI,CAAA;IACb,CAAC;IAED,SAAS,CAAC,MAAmB;QAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;QACpC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC;IAED,gBAAgB;IAChB,SAAS,CACP,KAAQ,EACR,OAAgC;QAEhC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAiD,EAAE,CAAC;YAC9F,IAAI,CAAC;gBACH,QAAQ,CAAC,OAAO,CAAC,CAAA;YACnB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,kCAAkC,IAAI,CAAC,MAAM,KAAK,KAAK,YAAY,EAAE,CAAC,CAAC,CAAA;YACvF,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,iFAAiF;AAEjF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA4B;IAC7D,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,OAAO,CAAA;IAEnD,MAAM,YAAY,GAAG,GAAG,OAAO,eAAe,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAA;IAEzE,yFAAyF;IACzF,0EAA0E;IAC1E,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,YAAY,CAAC,CAAA;IAEtC,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACvE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAA;YACV,MAAM,CAAC,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAA;QACrE,CAAC,EAAE,MAAM,CAAC,CAAA;QAEV,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;YAChB,YAAY,CAAC,OAAO,CAAC,CAAA;YACrB,MAAM,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAA;QAC7D,CAAC,CAAA;QAED,EAAE,CAAC,MAAM,GAAG,KAAK,IAAI,EAAE;YACrB,yEAAyE;YACzE,oEAAoE;YACpE,MAAM,EAAE,GAAG,IAAI,iBAAiB,CAAC;gBAC/B,UAAU,EAAE;oBACV,8CAA8C;oBAC9C,kFAAkF;oBAClF,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;oBAChF,GAAG,UAAU;iBACd;aACF,CAAC,CAAA;YAEF,oDAAoD;YACpD,EAAE,CAAC,cAAc,GAAG,CAAC,EAAE,EAAE,EAAE;gBACzB,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBACjB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAA;gBACnF,CAAC;YACH,CAAC,CAAA;YAED,6BAA6B;YAC7B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,WAAW,EAAE,CAAA;YACpC,MAAM,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAA;YACnC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAE1D,EAAE,CAAC,SAAS,GAAG,KAAK,EAAE,EAAE,EAAE,EAAE;gBAC1B,IAAI,GAAqB,CAAA;gBACzB,IAAI,CAAC;oBACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAc,CAAqB,CAAA;gBACzD,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAM;gBACR,CAAC;gBAED,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC1B,MAAM,EAAE,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;oBAC/D,OAAM;gBACR,CAAC;gBAED,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;oBACvB,IAAI,CAAC;wBACH,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAwB,CAAC,CAAA;oBAC5E,CAAC;oBAAC,MAAM,CAAC;wBACP,+CAA+C;oBACjD,CAAC;oBACD,OAAM;gBACR,CAAC;gBAED,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACzB,YAAY,CAAC,OAAO,CAAC,CAAA;oBACrB,EAAE,CAAC,KAAK,EAAE,CAAA;oBACV,EAAE,CAAC,KAAK,EAAE,CAAA;oBACV,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;oBACzD,OAAM;gBACR,CAAC;gBAED,+EAA+E;gBAC/E,uEAAuE;gBACvE,0EAA0E;gBAC1E,qEAAqE;gBACrE,IAAI,CAAC,aAAa;oBAAE,OAAM;gBAC1B,mBAAmB,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;YACzC,CAAC,CAAA;YAED,4EAA4E;YAC5E,qFAAqF;YACrF,EAAE,CAAC,uBAAuB,GAAG,GAAG,EAAE;gBAChC,IAAI,EAAE,CAAC,eAAe,KAAK,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC;oBACzD,+EAA+E;oBAC/E,8EAA8E;oBAC9E,MAAM,CAAC,GAAG,IAAI,kBAAkB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;oBAChD,aAAa,GAAG,CAAC,CAAA;oBACjB,YAAY,CAAC,OAAO,CAAC,CAAA;oBACrB,OAAO,CAAC,CAAC,CAAC,CAAA;gBACZ,CAAC;gBACD,IAAI,EAAE,CAAC,eAAe,KAAK,QAAQ,IAAI,EAAE,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;oBACvE,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,YAAY,CAAC,OAAO,CAAC,CAAA;wBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,CAAA;oBACpE,CAAC;gBACH,CAAC;YACH,CAAC,CAAA;YAED,qBAAqB;YACrB,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE;gBAClB,IAAI,CAAC,aAAa;oBAAE,OAAM;gBAC1B,aAAa,CAAC,SAAS,CAAC,YAAY,EAAE;oBACpC,MAAM,EAAE,QAAQ,EAAE,wBAAwB;oBAC1C,KAAK,EAAE,EAAE,CAAC,KAAK;oBACf,OAAO,EAAE,EAAE,CAAC,OAAO;iBACpB,CAAC,CAAA;gBACF,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,EAAE;oBACtB,aAAa,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;gBACjF,CAAC,CAAA;YACH,CAAC,CAAA;QACH,CAAC,CAAA;QAED,IAAI,aAAa,GAA8B,IAAI,CAAA;QAEnD,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE;YAClB,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,EAAE,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBACrB,aAAa,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;gBACjG,CAAC;gBACD,aAAa,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAA;YACrE,CAAC;QACH,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC;AAED,iFAAiF;AAEjF,SAAS,mBAAmB,CAAC,MAA0B,EAAE,GAAqB;IAC5E,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,YAAY;YACf,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,GAAiC,CAAC,CAAA;YACjE,MAAK;QACP,KAAK,gBAAgB;YACnB,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,GAAqC,CAAC,CAAA;YACzE,MAAK;QACP,KAAK,kBAAkB;YACrB,MAAM,CAAC,SAAS,CAAC,kBAAkB,EAAE,GAAuC,CAAC,CAAA;YAC7E,MAAK;QACP,KAAK,iBAAiB;YACpB,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,SAAS,EAAyB,CAAC,CAAA;YACxG,MAAK;QACP,KAAK,YAAY;YACf,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,GAAiC,CAAC,CAAA;YACjE,MAAK;QACP,KAAK,UAAU;YACb,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,GAA+B,CAAC,CAAA;YAC7D,MAAK;QACP,KAAK,YAAY;YACf,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YAClD,MAAK;QACP,KAAK,OAAO;YACV,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACnD,MAAK;IACT,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/protocol
|
|
3
|
+
* @description MessagePack encode/decode for Hall WebSocket frames.
|
|
4
|
+
*
|
|
5
|
+
* All Hall WebSocket frames are binary msgpack. The Rust server uses serde's
|
|
6
|
+
* `tag/content` encoding: `{ t: "messageType", d: { ...fields } }`.
|
|
7
|
+
*
|
|
8
|
+
* This module provides typed encode/decode functions that match the Rust
|
|
9
|
+
* protocol exactly. Runtime validation catches protocol drift early.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const bytes = encodeHallMessage({ t: 'createRoom', d: { roomId: 'abc', options: {} } })
|
|
14
|
+
* socket.send(bytes)
|
|
15
|
+
*
|
|
16
|
+
* socket.onmessage = (ev) => {
|
|
17
|
+
* const msg = decodeHallMessage(ev.data)
|
|
18
|
+
* if (msg.t === 'roomCreated') console.log(msg.d.sessionId)
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { HallClientMessage, HallServerMessage } from './types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Encode a {@link HallClientMessage} to msgpack bytes for transmission over WebSocket.
|
|
25
|
+
*
|
|
26
|
+
* @param msg - The typed client message to encode.
|
|
27
|
+
* @returns Binary msgpack payload ready to send via `WebSocket.send()`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function encodeHallMessage(msg: HallClientMessage): Uint8Array;
|
|
30
|
+
/**
|
|
31
|
+
* Decode a msgpack binary frame received from the Hall server.
|
|
32
|
+
*
|
|
33
|
+
* @param data - Raw bytes from a WebSocket binary message (`ev.data`).
|
|
34
|
+
* @returns The decoded {@link HallServerMessage}.
|
|
35
|
+
* @throws {Error} If the bytes are not valid msgpack or the decoded value is
|
|
36
|
+
* not a recognised server message object (missing `t` field).
|
|
37
|
+
*/
|
|
38
|
+
export declare function decodeHallMessage(data: ArrayBuffer | Uint8Array): HallServerMessage;
|
|
39
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/modules/hall/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEtE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,GAAG,UAAU,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,GAAG,iBAAiB,CAiBnF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/protocol
|
|
3
|
+
* @description MessagePack encode/decode for Hall WebSocket frames.
|
|
4
|
+
*
|
|
5
|
+
* All Hall WebSocket frames are binary msgpack. The Rust server uses serde's
|
|
6
|
+
* `tag/content` encoding: `{ t: "messageType", d: { ...fields } }`.
|
|
7
|
+
*
|
|
8
|
+
* This module provides typed encode/decode functions that match the Rust
|
|
9
|
+
* protocol exactly. Runtime validation catches protocol drift early.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const bytes = encodeHallMessage({ t: 'createRoom', d: { roomId: 'abc', options: {} } })
|
|
14
|
+
* socket.send(bytes)
|
|
15
|
+
*
|
|
16
|
+
* socket.onmessage = (ev) => {
|
|
17
|
+
* const msg = decodeHallMessage(ev.data)
|
|
18
|
+
* if (msg.t === 'roomCreated') console.log(msg.d.sessionId)
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { encode, decode } from '@msgpack/msgpack';
|
|
23
|
+
/**
|
|
24
|
+
* Encode a {@link HallClientMessage} to msgpack bytes for transmission over WebSocket.
|
|
25
|
+
*
|
|
26
|
+
* @param msg - The typed client message to encode.
|
|
27
|
+
* @returns Binary msgpack payload ready to send via `WebSocket.send()`.
|
|
28
|
+
*/
|
|
29
|
+
export function encodeHallMessage(msg) {
|
|
30
|
+
return encode(msg);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Decode a msgpack binary frame received from the Hall server.
|
|
34
|
+
*
|
|
35
|
+
* @param data - Raw bytes from a WebSocket binary message (`ev.data`).
|
|
36
|
+
* @returns The decoded {@link HallServerMessage}.
|
|
37
|
+
* @throws {Error} If the bytes are not valid msgpack or the decoded value is
|
|
38
|
+
* not a recognised server message object (missing `t` field).
|
|
39
|
+
*/
|
|
40
|
+
export function decodeHallMessage(data) {
|
|
41
|
+
const raw = decode(data instanceof ArrayBuffer ? new Uint8Array(data) : data);
|
|
42
|
+
if (typeof raw !== 'object' ||
|
|
43
|
+
raw === null ||
|
|
44
|
+
!('t' in raw) ||
|
|
45
|
+
typeof raw.t !== 'string') {
|
|
46
|
+
throw new Error(`Invalid Hall message: expected object with string "t" field, got ${JSON.stringify(raw)}`);
|
|
47
|
+
}
|
|
48
|
+
// Trust the server to send well-formed messages — full schema validation
|
|
49
|
+
// would duplicate the Rust type definitions and add runtime cost.
|
|
50
|
+
return raw;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/modules/hall/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAGjD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAsB;IACtD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA8B;IAC9D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,YAAY,WAAW,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAE7E,IACE,OAAO,GAAG,KAAK,QAAQ;QACvB,GAAG,KAAK,IAAI;QACZ,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QACb,OAAQ,GAA+B,CAAC,CAAC,KAAK,QAAQ,EACtD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,oEAAoE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAC1F,CAAA;IACH,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,OAAO,GAAwB,CAAA;AACjC,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/hall/server
|
|
3
|
+
* @description Server-side Hall client — product backend to Hall server control plane.
|
|
4
|
+
*
|
|
5
|
+
* `HallClient` maintains a single authenticated WebSocket connection from the product
|
|
6
|
+
* backend to `hall.soulcraft.com`. All room management (createRoom, closeRoom, session
|
|
7
|
+
* tokens, recording) goes through this connection.
|
|
8
|
+
*
|
|
9
|
+
* This module is **server-only** — it uses WebSocket, reconnect timers, and the
|
|
10
|
+
* product shared secret, none of which should ever reach a browser bundle.
|
|
11
|
+
*
|
|
12
|
+
* Use `createHallModule(options)` from `@soulcraft/sdk/server` to get a fully wired
|
|
13
|
+
* `HallModule` instance. Direct use of `HallClient` is for advanced scenarios.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { createHallModule } from '@soulcraft/sdk/server'
|
|
18
|
+
*
|
|
19
|
+
* const hall = createHallModule({
|
|
20
|
+
* url: process.env.HALL_URL!,
|
|
21
|
+
* productName: 'academy',
|
|
22
|
+
* secret: process.env.HALL_ACADEMY_SECRET!,
|
|
23
|
+
* })
|
|
24
|
+
* await hall.connect()
|
|
25
|
+
* const room = await hall.createRoom('cohort-123', { enableTranscription: true })
|
|
26
|
+
* room.on('transcript', (t) => console.log(t.text))
|
|
27
|
+
* const { token } = await hall.createSessionToken('cohort-123', 'user-456')
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import type { HallConnectionOptions, HallModule, HallRoom, HallRoomEvents, RoomOptions } from './types.js';
|
|
31
|
+
type Listener<T> = (event: T) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Concrete implementation of the {@link HallRoom} interface.
|
|
34
|
+
*
|
|
35
|
+
* Stores per-event listener sets and provides a typed dispatch method called
|
|
36
|
+
* internally by `HallClient` when the server pushes room events.
|
|
37
|
+
*/
|
|
38
|
+
export declare class HallRoomImpl implements HallRoom {
|
|
39
|
+
#private;
|
|
40
|
+
readonly roomId: string;
|
|
41
|
+
readonly sessionId: string;
|
|
42
|
+
constructor(roomId: string, sessionId: string);
|
|
43
|
+
on<K extends keyof HallRoomEvents>(event: K, listener: Listener<HallRoomEvents[K]>): this;
|
|
44
|
+
off<K extends keyof HallRoomEvents>(event: K, listener: Listener<HallRoomEvents[K]>): this;
|
|
45
|
+
/** @internal Dispatches an incoming server event to all registered listeners. */
|
|
46
|
+
_dispatch<K extends keyof HallRoomEvents>(event: K, payload: HallRoomEvents[K]): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Product-backend WebSocket client for the Hall real-time communication server.
|
|
50
|
+
*
|
|
51
|
+
* Create one instance per product process. Maintains a single authenticated control-plane
|
|
52
|
+
* WebSocket to `hall.soulcraft.com`. All room management and event routing goes through
|
|
53
|
+
* this single connection — do not create multiple instances per product.
|
|
54
|
+
*
|
|
55
|
+
* Auto-reconnects on unexpected disconnect (configurable via `reconnectDelayMs`).
|
|
56
|
+
* In-flight promises are rejected on disconnect; register `onReconnect` to re-create rooms.
|
|
57
|
+
*/
|
|
58
|
+
export declare class HallClient implements HallModule {
|
|
59
|
+
#private;
|
|
60
|
+
readonly url: string;
|
|
61
|
+
/**
|
|
62
|
+
* @param options - Connection options: url, productName, secret, and optional reconnectDelayMs.
|
|
63
|
+
*/
|
|
64
|
+
constructor(options: HallConnectionOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Connect to the Hall server and authenticate with the product shared secret.
|
|
67
|
+
* Must be called once at startup before any other method.
|
|
68
|
+
*
|
|
69
|
+
* @returns Resolves when `authOk` is received from the server.
|
|
70
|
+
* @throws {Error} If auth fails or the WebSocket cannot connect.
|
|
71
|
+
*/
|
|
72
|
+
connect(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Gracefully close all active rooms and disconnect from the Hall server.
|
|
75
|
+
* After calling this, the instance cannot be reconnected.
|
|
76
|
+
*/
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Register a listener for unexpected disconnects (not triggered by `close()`).
|
|
80
|
+
* Use this to log the event and prepare to re-create rooms after reconnect.
|
|
81
|
+
*
|
|
82
|
+
* @param listener - Called with a human-readable reason string (e.g. `"code 1006"`).
|
|
83
|
+
*/
|
|
84
|
+
onDisconnect(listener: (reason: string) => void): void;
|
|
85
|
+
/**
|
|
86
|
+
* Register a listener for successful reconnections.
|
|
87
|
+
* On reconnect, rooms from before the disconnect are gone — re-create them here.
|
|
88
|
+
*
|
|
89
|
+
* @param listener - Called with no arguments when the reconnect auth succeeds.
|
|
90
|
+
*/
|
|
91
|
+
onReconnect(listener: () => void): void;
|
|
92
|
+
/**
|
|
93
|
+
* Create a new room on the Hall server.
|
|
94
|
+
*
|
|
95
|
+
* @param roomId - Unique room identifier (e.g. Brainy session entity ID).
|
|
96
|
+
* @param options - Room configuration: peer limit, transcription, recording, concept list.
|
|
97
|
+
* @returns The HallRoom handle — register event listeners on it immediately.
|
|
98
|
+
* @throws {Error} If a room with the same ID already exists or the server returns an error.
|
|
99
|
+
*/
|
|
100
|
+
createRoom(roomId: string, options?: RoomOptions): Promise<HallRoomImpl>;
|
|
101
|
+
/**
|
|
102
|
+
* Close a room and disconnect all its peers.
|
|
103
|
+
*
|
|
104
|
+
* @param roomId - The room ID passed to `createRoom`.
|
|
105
|
+
* @throws {Error} If the server returns an error.
|
|
106
|
+
*/
|
|
107
|
+
closeRoom(roomId: string): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Return the IDs of all active rooms managed by this connection.
|
|
110
|
+
*
|
|
111
|
+
* @returns Array of room ID strings currently active on the server.
|
|
112
|
+
*/
|
|
113
|
+
listRooms(): Promise<string[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Return an active room handle by ID, or `undefined` if not found.
|
|
116
|
+
*
|
|
117
|
+
* @param roomId - The room ID passed to `createRoom`.
|
|
118
|
+
*/
|
|
119
|
+
getRoom(roomId: string): HallRoomImpl | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Mint a short-lived HMAC session token for a browser peer.
|
|
122
|
+
* Pass `{ token, hallUrl }` to the browser — **never** the product secret.
|
|
123
|
+
*
|
|
124
|
+
* @param roomId - The room the browser peer will join.
|
|
125
|
+
* @param peerId - The peer's unique identifier (e.g. authenticated user ID).
|
|
126
|
+
* @param ttlSecs - Token lifetime in seconds (default: 300).
|
|
127
|
+
* @returns `{ token, expiresAt }` — send `token` and `this.url` to the browser.
|
|
128
|
+
*/
|
|
129
|
+
createSessionToken(roomId: string, peerId: string, ttlSecs?: number): Promise<{
|
|
130
|
+
token: string;
|
|
131
|
+
expiresAt: number;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* Start per-track MKV recording for an active room.
|
|
135
|
+
* The room emits `recordingManifest` when `stopRecording` is called.
|
|
136
|
+
*
|
|
137
|
+
* @param roomId - The room to start recording.
|
|
138
|
+
*/
|
|
139
|
+
startRecording(roomId: string): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Stop recording for a room. Hall writes track files and emits `recordingManifest`
|
|
142
|
+
* on the room handle with absolute paths to the recorded MKV files.
|
|
143
|
+
*
|
|
144
|
+
* @param roomId - The room to stop recording.
|
|
145
|
+
*/
|
|
146
|
+
stopRecording(roomId: string): Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Create a server-mode Hall module that connects to the Hall standalone server.
|
|
150
|
+
*
|
|
151
|
+
* Returns a `HallModule` backed by a `HallClient`. Call `connect()` once at startup.
|
|
152
|
+
* In typical server mode SDK usage, `createSDK` calls this automatically when
|
|
153
|
+
* `hall` options are provided in `ServerSDKOptions`.
|
|
154
|
+
*
|
|
155
|
+
* @param options - Connection options: url, productName, secret, reconnectDelayMs.
|
|
156
|
+
* @returns A `HallModule` instance (not yet connected — call `module.connect()`).
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* import { createHallModule } from '@soulcraft/sdk/server'
|
|
161
|
+
*
|
|
162
|
+
* const hall = createHallModule({
|
|
163
|
+
* url: process.env.HALL_URL!,
|
|
164
|
+
* productName: 'academy',
|
|
165
|
+
* secret: process.env.HALL_ACADEMY_SECRET!,
|
|
166
|
+
* })
|
|
167
|
+
* await hall.connect()
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare function createHallModule(options: HallConnectionOptions): HallModule;
|
|
171
|
+
export {};
|
|
172
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/modules/hall/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EACV,qBAAqB,EACrB,UAAU,EACV,QAAQ,EACR,cAAc,EAEd,WAAW,EAQZ,MAAM,YAAY,CAAA;AAInB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;AAGrC;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,QAAQ;;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBAad,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAK7C,EAAE,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAKzF,GAAG,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IAK1F,iFAAiF;IACjF,SAAS,CAAC,CAAC,SAAS,MAAM,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI;CAStF;AAWD;;;;;;;;;GASG;AACH,qBAAa,UAAW,YAAW,UAAU;;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IAwBpB;;OAEG;gBACS,OAAO,EAAE,qBAAqB;IAS1C;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAItD;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAMvC;;;;;;;OAOG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ5E;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC;;;;OAIG;IACH,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ9B;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIjD;;;;;;;;OAQG;IACH,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAShD;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAyN7C;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAE3E"}
|