@marianmeres/webrtc 1.3.1 → 1.4.1
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/AGENTS.md +16 -17
- package/API.md +39 -43
- package/README.md +23 -24
- package/dist/types.d.ts +8 -10
- package/dist/types.js +20 -20
- package/dist/webrtc-manager.d.ts +11 -11
- package/dist/webrtc-manager.js +157 -188
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -41,10 +41,10 @@ development:
|
|
|
41
41
|
src/
|
|
42
42
|
mod.ts # Entry point, re-exports all public APIs
|
|
43
43
|
types.ts # Type definitions (interfaces, enums)
|
|
44
|
-
webrtc-manager.ts # Main
|
|
44
|
+
webrtc-manager.ts # Main WebRTCManager class
|
|
45
45
|
|
|
46
46
|
tests/
|
|
47
|
-
mocks.ts # Mock
|
|
47
|
+
mocks.ts # Mock WebRTCFactory for testing
|
|
48
48
|
webrtc-manager.test.ts # Deno unit tests
|
|
49
49
|
browser/
|
|
50
50
|
p2p-tests.ts # Browser integration tests
|
|
@@ -65,7 +65,7 @@ scripts/
|
|
|
65
65
|
|
|
66
66
|
## State Machine
|
|
67
67
|
|
|
68
|
-
### States (
|
|
68
|
+
### States (WebRTCState)
|
|
69
69
|
|
|
70
70
|
| State | Description | Valid Outgoing Transitions |
|
|
71
71
|
|-------|-------------|---------------------------|
|
|
@@ -77,7 +77,7 @@ scripts/
|
|
|
77
77
|
| DISCONNECTED | Connection closed, resources may be cleaned up | CONNECTING, RECONNECTING, IDLE |
|
|
78
78
|
| ERROR | Error state, requires reset() to recover | IDLE |
|
|
79
79
|
|
|
80
|
-
### Events (
|
|
80
|
+
### Events (WebRTCFsmEvent)
|
|
81
81
|
|
|
82
82
|
| Event | Value | Description |
|
|
83
83
|
|-------|-------|-------------|
|
|
@@ -114,7 +114,7 @@ ERROR --RESET--> IDLE
|
|
|
114
114
|
### Constructor
|
|
115
115
|
|
|
116
116
|
```typescript
|
|
117
|
-
new
|
|
117
|
+
new WebRTCManager<TContext = unknown>(factory: WebRTCFactory, config?: WebRTCManagerConfig)
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
**Type Parameter:** `TContext` - Optional type for the `context` property (default: `unknown`)
|
|
@@ -134,27 +134,26 @@ interface Logger {
|
|
|
134
134
|
|
|
135
135
|
Each method returns a string representation of the first argument, enabling patterns like `throw new Error(logger.error("msg"))`.
|
|
136
136
|
|
|
137
|
-
###
|
|
137
|
+
### WebRTCFactory Interface
|
|
138
138
|
|
|
139
139
|
```typescript
|
|
140
|
-
interface
|
|
140
|
+
interface WebRTCFactory {
|
|
141
141
|
createPeerConnection(config?: RTCConfiguration): RTCPeerConnection;
|
|
142
142
|
getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
|
|
143
143
|
enumerateDevices(): Promise<MediaDeviceInfo[]>;
|
|
144
144
|
}
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
###
|
|
147
|
+
### WebRTCManagerConfig Interface
|
|
148
148
|
|
|
149
149
|
```typescript
|
|
150
|
-
interface
|
|
150
|
+
interface WebRTCManagerConfig {
|
|
151
151
|
peerConfig?: RTCConfiguration; // ICE servers, certificates
|
|
152
152
|
enableMicrophone?: boolean; // Default: false
|
|
153
153
|
dataChannelLabel?: string; // Auto-create data channel
|
|
154
154
|
autoReconnect?: boolean; // Default: false
|
|
155
155
|
maxReconnectAttempts?: number; // Default: 5
|
|
156
156
|
reconnectDelay?: number; // Default: 1000ms
|
|
157
|
-
debug?: boolean; // Default: false
|
|
158
157
|
logger?: Logger; // Custom logger, falls back to console
|
|
159
158
|
}
|
|
160
159
|
```
|
|
@@ -172,7 +171,7 @@ interface GatherIceCandidatesOptions {
|
|
|
172
171
|
|
|
173
172
|
| Property | Type | Description |
|
|
174
173
|
|----------|------|-------------|
|
|
175
|
-
| state |
|
|
174
|
+
| state | WebRTCState | Current FSM state |
|
|
176
175
|
| localStream | MediaStream \| null | Local audio stream |
|
|
177
176
|
| remoteStream | MediaStream \| null | Remote audio stream |
|
|
178
177
|
| dataChannels | ReadonlyMap<string, RTCDataChannel> | Active data channels |
|
|
@@ -223,7 +222,7 @@ interface GatherIceCandidatesOptions {
|
|
|
223
222
|
|
|
224
223
|
| Method | Signature | Description |
|
|
225
224
|
|--------|-----------|-------------|
|
|
226
|
-
| on | `(event: keyof
|
|
225
|
+
| on | `(event: keyof WebRTCEvents, handler: (data: any) => void): () => void` | Subscribe to specific event |
|
|
227
226
|
| subscribe | `(handler: (state: OverallState) => void): () => void` | Subscribe to overall state (Svelte compatible) |
|
|
228
227
|
|
|
229
228
|
### Utility Methods
|
|
@@ -236,7 +235,7 @@ interface GatherIceCandidatesOptions {
|
|
|
236
235
|
|
|
237
236
|
| Constant | Value | Payload Type |
|
|
238
237
|
|----------|-------|--------------|
|
|
239
|
-
| EVENT_STATE_CHANGE | "state_change" |
|
|
238
|
+
| EVENT_STATE_CHANGE | "state_change" | WebRTCState |
|
|
240
239
|
| EVENT_LOCAL_STREAM | "local_stream" | MediaStream \| null |
|
|
241
240
|
| EVENT_REMOTE_STREAM | "remote_stream" | MediaStream \| null |
|
|
242
241
|
| EVENT_DATA_CHANNEL_OPEN | "data_channel_open" | RTCDataChannel |
|
|
@@ -337,7 +336,7 @@ deno task serve:example # Run signaling server
|
|
|
337
336
|
### Minimal P2P Setup
|
|
338
337
|
|
|
339
338
|
```typescript
|
|
340
|
-
const manager = new
|
|
339
|
+
const manager = new WebRTCManager(factory, { enableMicrophone: true });
|
|
341
340
|
await manager.initialize();
|
|
342
341
|
await manager.connect();
|
|
343
342
|
const offer = await manager.createOffer();
|
|
@@ -348,7 +347,7 @@ await manager.setLocalDescription(offer);
|
|
|
348
347
|
### With Data Channel
|
|
349
348
|
|
|
350
349
|
```typescript
|
|
351
|
-
const manager = new
|
|
350
|
+
const manager = new WebRTCManager(factory, { dataChannelLabel: "chat" });
|
|
352
351
|
manager.on("data_channel_message", ({ data }) => console.log(data));
|
|
353
352
|
// After connection...
|
|
354
353
|
manager.sendData("chat", "Hello!");
|
|
@@ -358,7 +357,7 @@ manager.sendData("chat", "Hello!");
|
|
|
358
357
|
|
|
359
358
|
```svelte
|
|
360
359
|
<script>
|
|
361
|
-
const manager = new
|
|
360
|
+
const manager = new WebRTCManager(factory, config);
|
|
362
361
|
// $manager reactive access to state
|
|
363
362
|
</script>
|
|
364
363
|
{$manager.state}
|
|
@@ -367,7 +366,7 @@ const manager = new WebRtcManager(factory, config);
|
|
|
367
366
|
### Auto-reconnection Handling
|
|
368
367
|
|
|
369
368
|
```typescript
|
|
370
|
-
const manager = new
|
|
369
|
+
const manager = new WebRTCManager(factory, {
|
|
371
370
|
autoReconnect: true,
|
|
372
371
|
maxReconnectAttempts: 5,
|
|
373
372
|
reconnectDelay: 1000,
|
package/API.md
CHANGED
|
@@ -4,7 +4,7 @@ Complete API documentation for `@marianmeres/webrtc`.
|
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
7
|
-
- [
|
|
7
|
+
- [WebRTCManager](#webrtcmanager)
|
|
8
8
|
- [Constructor](#constructor)
|
|
9
9
|
- [Properties](#properties)
|
|
10
10
|
- [Lifecycle Methods](#lifecycle-methods)
|
|
@@ -14,24 +14,24 @@ Complete API documentation for `@marianmeres/webrtc`.
|
|
|
14
14
|
- [Event Methods](#event-methods)
|
|
15
15
|
- [Utility Methods](#utility-methods)
|
|
16
16
|
- [Types](#types)
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
17
|
+
- [WebRTCFactory](#webrtcfactory)
|
|
18
|
+
- [WebRTCManagerConfig](#webrtcmanagerconfig)
|
|
19
|
+
- [WebRTCState](#webrtcstate)
|
|
20
|
+
- [WebRTCFsmEvent](#webrtcfsmevent)
|
|
21
|
+
- [WebRTCEvents](#webrtcevents)
|
|
22
22
|
- [Event Constants](#event-constants)
|
|
23
23
|
- [State Machine](#state-machine)
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## WebRTCManager
|
|
28
28
|
|
|
29
29
|
The main class for managing WebRTC connections.
|
|
30
30
|
|
|
31
31
|
### Constructor
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
|
-
new
|
|
34
|
+
new WebRTCManager<TContext = unknown>(factory: WebRTCFactory, config?: WebRTCManagerConfig)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
**Type Parameters:**
|
|
@@ -44,13 +44,13 @@ new WebRtcManager<TContext = unknown>(factory: WebRtcFactory, config?: WebRtcMan
|
|
|
44
44
|
|
|
45
45
|
| Name | Type | Required | Description |
|
|
46
46
|
|------|------|----------|-------------|
|
|
47
|
-
| factory | `
|
|
48
|
-
| config | `
|
|
47
|
+
| factory | `WebRTCFactory` | Yes | Factory for creating WebRTC primitives |
|
|
48
|
+
| config | `WebRTCManagerConfig` | No | Configuration options |
|
|
49
49
|
|
|
50
50
|
**Example:**
|
|
51
51
|
|
|
52
52
|
```typescript
|
|
53
|
-
import {
|
|
53
|
+
import { WebRTCManager } from '@marianmeres/webrtc';
|
|
54
54
|
|
|
55
55
|
const factory = {
|
|
56
56
|
createPeerConnection: (config) => new RTCPeerConnection(config),
|
|
@@ -58,7 +58,7 @@ const factory = {
|
|
|
58
58
|
enumerateDevices: () => navigator.mediaDevices.enumerateDevices(),
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
const manager = new
|
|
61
|
+
const manager = new WebRTCManager(factory, {
|
|
62
62
|
peerConfig: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] },
|
|
63
63
|
enableMicrophone: true,
|
|
64
64
|
autoReconnect: true,
|
|
@@ -72,12 +72,12 @@ const manager = new WebRtcManager(factory, {
|
|
|
72
72
|
#### state
|
|
73
73
|
|
|
74
74
|
```typescript
|
|
75
|
-
get state():
|
|
75
|
+
get state(): WebRTCState
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
Returns the current state of the WebRTC connection.
|
|
79
79
|
|
|
80
|
-
**Returns:** `
|
|
80
|
+
**Returns:** `WebRTCState` - One of: `IDLE`, `INITIALIZING`, `CONNECTING`, `CONNECTED`, `RECONNECTING`, `DISCONNECTED`, `ERROR`
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
@@ -145,12 +145,12 @@ User-defined context object for storing arbitrary data associated with this mana
|
|
|
145
145
|
|
|
146
146
|
```typescript
|
|
147
147
|
// With type parameter for full type safety:
|
|
148
|
-
const manager = new
|
|
148
|
+
const manager = new WebRTCManager<{ audioStream: MediaStream; sessionId: string }>(factory);
|
|
149
149
|
manager.context = { audioStream: myStream, sessionId: '123' };
|
|
150
150
|
manager.context.audioStream; // typed as MediaStream
|
|
151
151
|
|
|
152
152
|
// Without type parameter (backwards compatible):
|
|
153
|
-
const manager = new
|
|
153
|
+
const manager = new WebRTCManager(factory);
|
|
154
154
|
manager.context = { anything: 'goes' };
|
|
155
155
|
```
|
|
156
156
|
|
|
@@ -614,9 +614,9 @@ stats?.forEach(report => {
|
|
|
614
614
|
#### on()
|
|
615
615
|
|
|
616
616
|
```typescript
|
|
617
|
-
on<K extends keyof
|
|
617
|
+
on<K extends keyof WebRTCEvents>(
|
|
618
618
|
event: K,
|
|
619
|
-
handler: (data:
|
|
619
|
+
handler: (data: WebRTCEvents[K]) => void
|
|
620
620
|
): () => void
|
|
621
621
|
```
|
|
622
622
|
|
|
@@ -626,7 +626,7 @@ Subscribe to a specific WebRTC event.
|
|
|
626
626
|
|
|
627
627
|
| Name | Type | Description |
|
|
628
628
|
|------|------|-------------|
|
|
629
|
-
| event | `keyof
|
|
629
|
+
| event | `keyof WebRTCEvents` | Event name |
|
|
630
630
|
| handler | `function` | Callback receiving event data |
|
|
631
631
|
|
|
632
632
|
**Returns:** `() => void` - Unsubscribe function
|
|
@@ -661,7 +661,7 @@ Subscribe to the overall state of the manager. Svelte store compatible - immedia
|
|
|
661
661
|
|
|
662
662
|
```typescript
|
|
663
663
|
{
|
|
664
|
-
state:
|
|
664
|
+
state: WebRTCState;
|
|
665
665
|
localStream: MediaStream | null;
|
|
666
666
|
remoteStream: MediaStream | null;
|
|
667
667
|
dataChannels: ReadonlyMap<string, RTCDataChannel>;
|
|
@@ -675,7 +675,7 @@ Subscribe to the overall state of the manager. Svelte store compatible - immedia
|
|
|
675
675
|
|
|
676
676
|
```svelte
|
|
677
677
|
<script>
|
|
678
|
-
const manager = new
|
|
678
|
+
const manager = new WebRTCManager(factory, config);
|
|
679
679
|
</script>
|
|
680
680
|
|
|
681
681
|
<p>State: {$manager.state}</p>
|
|
@@ -736,20 +736,19 @@ import { clog } from '@marianmeres/clog';
|
|
|
736
736
|
|
|
737
737
|
const logger = clog('WebRTC');
|
|
738
738
|
|
|
739
|
-
const manager = new
|
|
740
|
-
debug: true,
|
|
739
|
+
const manager = new WebRTCManager(factory, {
|
|
741
740
|
logger: logger,
|
|
742
741
|
});
|
|
743
742
|
```
|
|
744
743
|
|
|
745
744
|
---
|
|
746
745
|
|
|
747
|
-
###
|
|
746
|
+
### WebRTCFactory
|
|
748
747
|
|
|
749
748
|
Interface for dependency injection of WebRTC primitives.
|
|
750
749
|
|
|
751
750
|
```typescript
|
|
752
|
-
interface
|
|
751
|
+
interface WebRTCFactory {
|
|
753
752
|
createPeerConnection(config?: RTCConfiguration): RTCPeerConnection;
|
|
754
753
|
getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
|
|
755
754
|
enumerateDevices(): Promise<MediaDeviceInfo[]>;
|
|
@@ -759,7 +758,7 @@ interface WebRtcFactory {
|
|
|
759
758
|
**Browser Implementation:**
|
|
760
759
|
|
|
761
760
|
```typescript
|
|
762
|
-
const factory:
|
|
761
|
+
const factory: WebRTCFactory = {
|
|
763
762
|
createPeerConnection: (config) => new RTCPeerConnection(config),
|
|
764
763
|
getUserMedia: (constraints) => navigator.mediaDevices.getUserMedia(constraints),
|
|
765
764
|
enumerateDevices: () => navigator.mediaDevices.enumerateDevices(),
|
|
@@ -768,12 +767,12 @@ const factory: WebRtcFactory = {
|
|
|
768
767
|
|
|
769
768
|
---
|
|
770
769
|
|
|
771
|
-
###
|
|
770
|
+
### WebRTCManagerConfig
|
|
772
771
|
|
|
773
|
-
Configuration options for
|
|
772
|
+
Configuration options for WebRTCManager.
|
|
774
773
|
|
|
775
774
|
```typescript
|
|
776
|
-
interface
|
|
775
|
+
interface WebRTCManagerConfig {
|
|
777
776
|
/** RTCConfiguration for ICE servers, certificates, etc. */
|
|
778
777
|
peerConfig?: RTCConfiguration;
|
|
779
778
|
|
|
@@ -802,9 +801,6 @@ interface WebRtcManagerConfig {
|
|
|
802
801
|
strategy: "ice-restart" | "full";
|
|
803
802
|
}) => boolean;
|
|
804
803
|
|
|
805
|
-
/** Enable debug logging. Default: false */
|
|
806
|
-
debug?: boolean;
|
|
807
|
-
|
|
808
804
|
/** Custom logger instance. If not provided, falls back to console. */
|
|
809
805
|
logger?: Logger;
|
|
810
806
|
}
|
|
@@ -812,12 +808,12 @@ interface WebRtcManagerConfig {
|
|
|
812
808
|
|
|
813
809
|
---
|
|
814
810
|
|
|
815
|
-
###
|
|
811
|
+
### WebRTCState
|
|
816
812
|
|
|
817
813
|
Enum of possible connection states.
|
|
818
814
|
|
|
819
815
|
```typescript
|
|
820
|
-
enum
|
|
816
|
+
enum WebRTCState {
|
|
821
817
|
IDLE = "IDLE",
|
|
822
818
|
INITIALIZING = "INITIALIZING",
|
|
823
819
|
CONNECTING = "CONNECTING",
|
|
@@ -840,12 +836,12 @@ enum WebRtcState {
|
|
|
840
836
|
|
|
841
837
|
---
|
|
842
838
|
|
|
843
|
-
###
|
|
839
|
+
### WebRTCFsmEvent
|
|
844
840
|
|
|
845
841
|
Internal FSM events (for reference).
|
|
846
842
|
|
|
847
843
|
```typescript
|
|
848
|
-
enum
|
|
844
|
+
enum WebRTCFsmEvent {
|
|
849
845
|
INIT = "initialize",
|
|
850
846
|
CONNECT = "connect",
|
|
851
847
|
CONNECTED = "connected",
|
|
@@ -858,13 +854,13 @@ enum WebRtcFsmEvent {
|
|
|
858
854
|
|
|
859
855
|
---
|
|
860
856
|
|
|
861
|
-
###
|
|
857
|
+
### WebRTCEvents
|
|
862
858
|
|
|
863
859
|
Type definition for all events and their payloads.
|
|
864
860
|
|
|
865
861
|
```typescript
|
|
866
|
-
interface
|
|
867
|
-
state_change:
|
|
862
|
+
interface WebRTCEvents {
|
|
863
|
+
state_change: WebRTCState;
|
|
868
864
|
local_stream: MediaStream | null;
|
|
869
865
|
remote_stream: MediaStream | null;
|
|
870
866
|
data_channel_open: RTCDataChannel;
|
|
@@ -883,11 +879,11 @@ interface WebRtcEvents {
|
|
|
883
879
|
|
|
884
880
|
## Event Constants
|
|
885
881
|
|
|
886
|
-
Static event name constants on `
|
|
882
|
+
Static event name constants on `WebRTCManager`.
|
|
887
883
|
|
|
888
884
|
| Constant | Value | Payload |
|
|
889
885
|
|----------|-------|---------|
|
|
890
|
-
| `EVENT_STATE_CHANGE` | `"state_change"` | `
|
|
886
|
+
| `EVENT_STATE_CHANGE` | `"state_change"` | `WebRTCState` |
|
|
891
887
|
| `EVENT_LOCAL_STREAM` | `"local_stream"` | `MediaStream \| null` |
|
|
892
888
|
| `EVENT_REMOTE_STREAM` | `"remote_stream"` | `MediaStream \| null` |
|
|
893
889
|
| `EVENT_DATA_CHANNEL_OPEN` | `"data_channel_open"` | `RTCDataChannel` |
|
|
@@ -903,7 +899,7 @@ Static event name constants on `WebRtcManager`.
|
|
|
903
899
|
**Usage:**
|
|
904
900
|
|
|
905
901
|
```typescript
|
|
906
|
-
manager.on(
|
|
902
|
+
manager.on(WebRTCManager.EVENT_ICE_CANDIDATE, (candidate) => {
|
|
907
903
|
// Send to remote peer
|
|
908
904
|
});
|
|
909
905
|
```
|
|
@@ -1003,7 +999,7 @@ Use the `shouldReconnect` callback to suppress reconnection when the peer discon
|
|
|
1003
999
|
```typescript
|
|
1004
1000
|
let peerLeftIntentionally = false;
|
|
1005
1001
|
|
|
1006
|
-
const manager = new
|
|
1002
|
+
const manager = new WebRTCManager(factory, {
|
|
1007
1003
|
autoReconnect: true,
|
|
1008
1004
|
shouldReconnect: ({ attempt, maxAttempts, strategy }) => {
|
|
1009
1005
|
// Return false to suppress reconnection
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ npm install @marianmeres/webrtc
|
|
|
23
23
|
|
|
24
24
|
## High-Level Overview
|
|
25
25
|
|
|
26
|
-
The `
|
|
26
|
+
The `WebRTCManager` class handles the complete WebRTC connection lifecycle:
|
|
27
27
|
|
|
28
28
|
1. **Initialization**: Sets up RTCPeerConnection, media streams, and data channels
|
|
29
29
|
2. **Connection Management**: Handles state transitions, reconnection, and cleanup
|
|
@@ -38,12 +38,12 @@ The manager doesn't handle the signaling transport layer - you're responsible fo
|
|
|
38
38
|
### Constructor
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
|
-
const manager = new
|
|
41
|
+
const manager = new WebRTCManager<TContext>(factory, config);
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
- `TContext`: Optional type parameter for the `context` property (default: `unknown`)
|
|
45
45
|
|
|
46
|
-
- `factory`: Object implementing `
|
|
46
|
+
- `factory`: Object implementing `WebRTCFactory` interface (provides `createPeerConnection`, `getUserMedia`, `enumerateDevices`)
|
|
47
47
|
- `config`: Optional configuration object
|
|
48
48
|
|
|
49
49
|
**Configuration Options:**
|
|
@@ -55,13 +55,12 @@ const manager = new WebRtcManager<TContext>(factory, config);
|
|
|
55
55
|
- `reconnectDelay`: Initial reconnection delay in ms (default: 1000)
|
|
56
56
|
- `fullReconnectTimeout`: Timeout in ms for full reconnection to succeed (default: 30000)
|
|
57
57
|
- `shouldReconnect`: Callback to control whether reconnection should proceed (see below)
|
|
58
|
-
- `debug`: Enable debug logging (default: false)
|
|
59
58
|
- `logger`: Custom logger instance implementing `Logger` interface (default: console)
|
|
60
59
|
|
|
61
60
|
### State and Properties
|
|
62
61
|
|
|
63
62
|
```typescript
|
|
64
|
-
manager.state // Current
|
|
63
|
+
manager.state // Current WebRTCState
|
|
65
64
|
manager.localStream // MediaStream | null
|
|
66
65
|
manager.remoteStream // MediaStream | null
|
|
67
66
|
manager.dataChannels // ReadonlyMap<string, RTCDataChannel>
|
|
@@ -147,7 +146,7 @@ You might want to keep `enableMicrophone: false` even when your application uses
|
|
|
147
146
|
To use your own audio stream, access the `peerConnection` directly and add tracks after initialization:
|
|
148
147
|
|
|
149
148
|
```typescript
|
|
150
|
-
const manager = new
|
|
149
|
+
const manager = new WebRTCManager(factory, {
|
|
151
150
|
peerConfig: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] },
|
|
152
151
|
enableMicrophone: false, // We'll handle the audio stream ourselves
|
|
153
152
|
});
|
|
@@ -186,7 +185,7 @@ const offer = await manager.createOffer();
|
|
|
186
185
|
|
|
187
186
|
```typescript
|
|
188
187
|
// Subscribe to specific event
|
|
189
|
-
const unsub = manager.on(
|
|
188
|
+
const unsub = manager.on(WebRTCManager.EVENT_STATE_CHANGE, (state) => {
|
|
190
189
|
console.log('State changed:', state);
|
|
191
190
|
});
|
|
192
191
|
|
|
@@ -218,7 +217,7 @@ When `autoReconnect` is enabled, you can use the `shouldReconnect` callback to c
|
|
|
218
217
|
```typescript
|
|
219
218
|
let peerLeftIntentionally = false;
|
|
220
219
|
|
|
221
|
-
const manager = new
|
|
220
|
+
const manager = new WebRTCManager(factory, {
|
|
222
221
|
autoReconnect: true,
|
|
223
222
|
shouldReconnect: ({ attempt, maxAttempts, strategy }) => {
|
|
224
223
|
if (peerLeftIntentionally) {
|
|
@@ -229,7 +228,7 @@ const manager = new WebRtcManager(factory, {
|
|
|
229
228
|
});
|
|
230
229
|
|
|
231
230
|
// Listen for "goodbye" message from peer before they disconnect
|
|
232
|
-
manager.on(
|
|
231
|
+
manager.on(WebRTCManager.EVENT_DATA_CHANNEL_MESSAGE, ({ data }) => {
|
|
233
232
|
const msg = JSON.parse(data);
|
|
234
233
|
if (msg.type === 'bye') {
|
|
235
234
|
peerLeftIntentionally = true;
|
|
@@ -260,7 +259,7 @@ When a full reconnection is triggered, the manager will:
|
|
|
260
259
|
**Important:** The manager cannot automatically complete the signaling handshake for full reconnections. You must listen for the `reconnecting` event and re-establish signaling when the strategy is `'full'`:
|
|
261
260
|
|
|
262
261
|
```typescript
|
|
263
|
-
manager.on(
|
|
262
|
+
manager.on(WebRTCManager.EVENT_RECONNECTING, async ({ attempt, strategy }) => {
|
|
264
263
|
console.log(`Reconnecting (attempt ${attempt}, strategy: ${strategy})`);
|
|
265
264
|
|
|
266
265
|
if (strategy === 'full') {
|
|
@@ -280,7 +279,7 @@ If the full reconnection doesn't reach `CONNECTED` state within `fullReconnectTi
|
|
|
280
279
|
### Basic Usage (Vanilla JavaScript)
|
|
281
280
|
|
|
282
281
|
```typescript
|
|
283
|
-
import {
|
|
282
|
+
import { WebRTCManager, WebRTCState } from '@marianmeres/webrtc';
|
|
284
283
|
|
|
285
284
|
// Create factory (browser implementation)
|
|
286
285
|
const factory = {
|
|
@@ -290,7 +289,7 @@ const factory = {
|
|
|
290
289
|
};
|
|
291
290
|
|
|
292
291
|
// Create manager
|
|
293
|
-
const manager = new
|
|
292
|
+
const manager = new WebRTCManager(factory, {
|
|
294
293
|
peerConfig: {
|
|
295
294
|
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
|
|
296
295
|
},
|
|
@@ -299,12 +298,12 @@ const manager = new WebRtcManager(factory, {
|
|
|
299
298
|
});
|
|
300
299
|
|
|
301
300
|
// Subscribe to events
|
|
302
|
-
manager.on(
|
|
301
|
+
manager.on(WebRTCManager.EVENT_ICE_CANDIDATE, (candidate) => {
|
|
303
302
|
// Send candidate to remote peer via your signaling channel
|
|
304
303
|
signalingChannel.send({ type: 'candidate', candidate });
|
|
305
304
|
});
|
|
306
305
|
|
|
307
|
-
manager.on(
|
|
306
|
+
manager.on(WebRTCManager.EVENT_REMOTE_STREAM, (stream) => {
|
|
308
307
|
// Attach remote stream to audio element
|
|
309
308
|
audioElement.srcObject = stream;
|
|
310
309
|
});
|
|
@@ -332,7 +331,7 @@ signalingChannel.onmessage = async (msg) => {
|
|
|
332
331
|
|
|
333
332
|
```svelte
|
|
334
333
|
<script>
|
|
335
|
-
import {
|
|
334
|
+
import { WebRTCManager, WebRTCState } from '@marianmeres/webrtc';
|
|
336
335
|
import { onMount } from 'svelte';
|
|
337
336
|
|
|
338
337
|
const factory = {
|
|
@@ -341,7 +340,7 @@ signalingChannel.onmessage = async (msg) => {
|
|
|
341
340
|
enumerateDevices: () => navigator.mediaDevices.enumerateDevices(),
|
|
342
341
|
};
|
|
343
342
|
|
|
344
|
-
const manager = new
|
|
343
|
+
const manager = new WebRTCManager(factory, {
|
|
345
344
|
peerConfig: {
|
|
346
345
|
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
|
|
347
346
|
},
|
|
@@ -356,7 +355,7 @@ signalingChannel.onmessage = async (msg) => {
|
|
|
356
355
|
|
|
357
356
|
onMount(() => {
|
|
358
357
|
const unsubDevices = manager.on(
|
|
359
|
-
|
|
358
|
+
WebRTCManager.EVENT_DEVICE_CHANGED,
|
|
360
359
|
(devs) => devices = devs
|
|
361
360
|
);
|
|
362
361
|
|
|
@@ -398,14 +397,14 @@ signalingChannel.onmessage = async (msg) => {
|
|
|
398
397
|
### Complete Peer-to-Peer Example
|
|
399
398
|
|
|
400
399
|
```typescript
|
|
401
|
-
import {
|
|
400
|
+
import { WebRTCManager } from '@marianmores/webrtc';
|
|
402
401
|
|
|
403
402
|
class P2PConnection {
|
|
404
|
-
manager:
|
|
403
|
+
manager: WebRTCManager;
|
|
405
404
|
signalingChannel: WebSocket;
|
|
406
405
|
|
|
407
406
|
constructor(signalingUrl: string) {
|
|
408
|
-
this.manager = new
|
|
407
|
+
this.manager = new WebRTCManager(
|
|
409
408
|
{
|
|
410
409
|
createPeerConnection: (config) => new RTCPeerConnection(config),
|
|
411
410
|
getUserMedia: (constraints) => navigator.mediaDevices.getUserMedia(constraints),
|
|
@@ -446,7 +445,7 @@ class P2PConnection {
|
|
|
446
445
|
|
|
447
446
|
setupManagerEvents() {
|
|
448
447
|
// Send ICE candidates to remote peer
|
|
449
|
-
this.manager.on(
|
|
448
|
+
this.manager.on(WebRTCManager.EVENT_ICE_CANDIDATE, (candidate) => {
|
|
450
449
|
this.signalingChannel.send(JSON.stringify({
|
|
451
450
|
type: 'candidate',
|
|
452
451
|
candidate,
|
|
@@ -454,18 +453,18 @@ class P2PConnection {
|
|
|
454
453
|
});
|
|
455
454
|
|
|
456
455
|
// Handle remote audio stream
|
|
457
|
-
this.manager.on(
|
|
456
|
+
this.manager.on(WebRTCManager.EVENT_REMOTE_STREAM, (stream) => {
|
|
458
457
|
const audio = document.getElementById('remote-audio') as HTMLAudioElement;
|
|
459
458
|
audio.srcObject = stream;
|
|
460
459
|
});
|
|
461
460
|
|
|
462
461
|
// Handle data channel messages
|
|
463
|
-
this.manager.on(
|
|
462
|
+
this.manager.on(WebRTCManager.EVENT_DATA_CHANNEL_MESSAGE, ({ data }) => {
|
|
464
463
|
console.log('Received message:', data);
|
|
465
464
|
});
|
|
466
465
|
|
|
467
466
|
// Handle reconnection
|
|
468
|
-
this.manager.on(
|
|
467
|
+
this.manager.on(WebRTCManager.EVENT_RECONNECTING, ({ attempt, strategy }) => {
|
|
469
468
|
console.log(`Reconnecting (attempt ${attempt}, strategy: ${strategy})`);
|
|
470
469
|
if (strategy === 'full') {
|
|
471
470
|
// For full reconnection, we need to re-do the signaling handshake
|
package/dist/types.d.ts
CHANGED
|
@@ -10,10 +10,10 @@ export interface Logger {
|
|
|
10
10
|
error: (...args: any[]) => any;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Configuration options for
|
|
13
|
+
* Configuration options for WebRTCManager.
|
|
14
14
|
* All options are optional with sensible defaults.
|
|
15
15
|
*/
|
|
16
|
-
export interface
|
|
16
|
+
export interface WebRTCManagerConfig {
|
|
17
17
|
/** Initial peer configuration (ICE servers, etc.) */
|
|
18
18
|
peerConfig?: RTCConfiguration;
|
|
19
19
|
/** Whether to enable microphone initially. Defaults to false. */
|
|
@@ -42,8 +42,6 @@ export interface WebRtcManagerConfig {
|
|
|
42
42
|
/** Strategy that will be used: "ice-restart" for first attempts, "full" for later */
|
|
43
43
|
strategy: "ice-restart" | "full";
|
|
44
44
|
}) => boolean;
|
|
45
|
-
/** Enable debug logging. Defaults to false. */
|
|
46
|
-
debug?: boolean;
|
|
47
45
|
/** Custom logger instance. If not provided, falls back to console. */
|
|
48
46
|
logger?: Logger;
|
|
49
47
|
}
|
|
@@ -51,7 +49,7 @@ export interface WebRtcManagerConfig {
|
|
|
51
49
|
* Factory interface for creating WebRTC primitives.
|
|
52
50
|
* Allows dependency injection of browser APIs for testing and flexibility.
|
|
53
51
|
*/
|
|
54
|
-
export interface
|
|
52
|
+
export interface WebRTCFactory {
|
|
55
53
|
/**
|
|
56
54
|
* Creates a new RTCPeerConnection instance.
|
|
57
55
|
* @param config - Optional RTCConfiguration for ICE servers, certificates, etc.
|
|
@@ -74,7 +72,7 @@ export interface WebRtcFactory {
|
|
|
74
72
|
* Possible states of the WebRTC connection lifecycle.
|
|
75
73
|
* The manager transitions between these states based on connection events.
|
|
76
74
|
*/
|
|
77
|
-
export declare enum
|
|
75
|
+
export declare enum WebRTCState {
|
|
78
76
|
/** Initial state, no resources allocated. */
|
|
79
77
|
IDLE = "IDLE",
|
|
80
78
|
/** Creating peer connection and setting up media tracks. */
|
|
@@ -94,7 +92,7 @@ export declare enum WebRtcState {
|
|
|
94
92
|
* Internal FSM events that trigger state transitions.
|
|
95
93
|
* These events are dispatched internally by the manager methods.
|
|
96
94
|
*/
|
|
97
|
-
export declare enum
|
|
95
|
+
export declare enum WebRTCFsmEvent {
|
|
98
96
|
/** Triggers transition from IDLE to INITIALIZING. */
|
|
99
97
|
INIT = "initialize",
|
|
100
98
|
/** Triggers transition to CONNECTING state. */
|
|
@@ -114,9 +112,9 @@ export declare enum WebRtcFsmEvent {
|
|
|
114
112
|
* Type definitions for all WebRTC manager events and their payloads.
|
|
115
113
|
* Use with the `on()` method to subscribe to specific events.
|
|
116
114
|
*/
|
|
117
|
-
export interface
|
|
118
|
-
/** Emitted when connection state changes. Payload: the new
|
|
119
|
-
state_change:
|
|
115
|
+
export interface WebRTCEvents {
|
|
116
|
+
/** Emitted when connection state changes. Payload: the new WebRTCState. */
|
|
117
|
+
state_change: WebRTCState;
|
|
120
118
|
/** Emitted when local media stream changes. Payload: MediaStream or null if disabled. */
|
|
121
119
|
local_stream: MediaStream | null;
|
|
122
120
|
/** Emitted when remote media stream is received. Payload: MediaStream or null. */
|