@xtr-dev/rondevu-client 0.0.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/README.md +234 -0
- package/dist/client.d.ts +127 -0
- package/dist/client.js +182 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +48 -0
- package/dist/types.d.ts +146 -0
- package/dist/types.js +2 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# @xtr-dev/rondevu-client
|
|
2
|
+
|
|
3
|
+
TypeScript client for interacting with the Rondevu peer signaling and discovery server. Provides a simple, type-safe API for WebRTC peer discovery and connection establishment.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @xtr-dev/rondevu-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Setup
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { RondevuClient } from '@xtr-dev/rondevu-client';
|
|
17
|
+
|
|
18
|
+
const client = new RondevuClient({
|
|
19
|
+
baseUrl: 'https://rondevu.example.com',
|
|
20
|
+
// Optional: custom origin for session isolation
|
|
21
|
+
origin: 'https://myapp.com'
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Peer Discovery Flow
|
|
26
|
+
|
|
27
|
+
#### 1. List Available Topics
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// Get all topics with peer counts
|
|
31
|
+
const { topics, pagination } = await client.listTopics();
|
|
32
|
+
|
|
33
|
+
topics.forEach(topic => {
|
|
34
|
+
console.log(`${topic.topic}: ${topic.count} peers available`);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### 2. Create an Offer (Peer A)
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// Announce availability in a topic
|
|
42
|
+
const { code } = await client.createOffer('my-room', {
|
|
43
|
+
info: 'peer-A-unique-id',
|
|
44
|
+
offer: webrtcOfferData
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log('Session code:', code);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### 3. Discover Peers (Peer B)
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// Find available peers in a topic
|
|
54
|
+
const { sessions } = await client.listSessions('my-room');
|
|
55
|
+
|
|
56
|
+
// Filter out your own sessions
|
|
57
|
+
const otherPeers = sessions.filter(s => s.info !== 'my-peer-id');
|
|
58
|
+
|
|
59
|
+
if (otherPeers.length > 0) {
|
|
60
|
+
const peer = otherPeers[0];
|
|
61
|
+
console.log('Found peer:', peer.info);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### 4. Send Answer (Peer B)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// Connect to a peer by answering their offer
|
|
69
|
+
await client.sendAnswer({
|
|
70
|
+
code: peer.code,
|
|
71
|
+
answer: webrtcAnswerData,
|
|
72
|
+
side: 'answerer'
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### 5. Poll for Data (Both Peers)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// Offerer polls for answer
|
|
80
|
+
const offererData = await client.poll(code, 'offerer');
|
|
81
|
+
if (offererData.answer) {
|
|
82
|
+
console.log('Received answer from peer');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Answerer polls for offer details
|
|
86
|
+
const answererData = await client.poll(code, 'answerer');
|
|
87
|
+
console.log('Offer candidates:', answererData.offerCandidates);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### 6. Exchange ICE Candidates
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Send additional signaling data
|
|
94
|
+
await client.sendAnswer({
|
|
95
|
+
code: sessionCode,
|
|
96
|
+
candidate: iceCandidate,
|
|
97
|
+
side: 'offerer' // or 'answerer'
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Health Check
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const health = await client.health();
|
|
105
|
+
console.log('Server status:', health.status);
|
|
106
|
+
console.log('Timestamp:', health.timestamp);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API Reference
|
|
110
|
+
|
|
111
|
+
### `RondevuClient`
|
|
112
|
+
|
|
113
|
+
#### Constructor
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
new RondevuClient(options: RondevuClientOptions)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Options:**
|
|
120
|
+
- `baseUrl` (string, required): Base URL of the Rondevu server
|
|
121
|
+
- `origin` (string, optional): Origin header for session isolation (defaults to baseUrl origin)
|
|
122
|
+
- `fetch` (function, optional): Custom fetch implementation (for Node.js)
|
|
123
|
+
|
|
124
|
+
#### Methods
|
|
125
|
+
|
|
126
|
+
##### `listTopics(page?, limit?)`
|
|
127
|
+
|
|
128
|
+
Lists all topics with peer counts.
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
- `page` (number, optional): Page number, default 1
|
|
132
|
+
- `limit` (number, optional): Results per page, default 100, max 1000
|
|
133
|
+
|
|
134
|
+
**Returns:** `Promise<ListTopicsResponse>`
|
|
135
|
+
|
|
136
|
+
##### `listSessions(topic)`
|
|
137
|
+
|
|
138
|
+
Discovers available peers for a given topic.
|
|
139
|
+
|
|
140
|
+
**Parameters:**
|
|
141
|
+
- `topic` (string): Topic identifier
|
|
142
|
+
|
|
143
|
+
**Returns:** `Promise<ListSessionsResponse>`
|
|
144
|
+
|
|
145
|
+
##### `createOffer(topic, request)`
|
|
146
|
+
|
|
147
|
+
Announces peer availability and creates a new session.
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
- `topic` (string): Topic identifier (max 256 characters)
|
|
151
|
+
- `request` (CreateOfferRequest):
|
|
152
|
+
- `info` (string): Peer identifier/metadata (max 1024 characters)
|
|
153
|
+
- `offer` (string): WebRTC signaling data
|
|
154
|
+
|
|
155
|
+
**Returns:** `Promise<CreateOfferResponse>`
|
|
156
|
+
|
|
157
|
+
##### `sendAnswer(request)`
|
|
158
|
+
|
|
159
|
+
Sends an answer or candidate to an existing session.
|
|
160
|
+
|
|
161
|
+
**Parameters:**
|
|
162
|
+
- `request` (AnswerRequest):
|
|
163
|
+
- `code` (string): Session UUID
|
|
164
|
+
- `answer` (string, optional): Answer signaling data
|
|
165
|
+
- `candidate` (string, optional): ICE candidate data
|
|
166
|
+
- `side` ('offerer' | 'answerer'): Which peer is sending
|
|
167
|
+
|
|
168
|
+
**Returns:** `Promise<AnswerResponse>`
|
|
169
|
+
|
|
170
|
+
##### `poll(code, side)`
|
|
171
|
+
|
|
172
|
+
Polls for session data from the other peer.
|
|
173
|
+
|
|
174
|
+
**Parameters:**
|
|
175
|
+
- `code` (string): Session UUID
|
|
176
|
+
- `side` ('offerer' | 'answerer'): Which side is polling
|
|
177
|
+
|
|
178
|
+
**Returns:** `Promise<PollOffererResponse | PollAnswererResponse>`
|
|
179
|
+
|
|
180
|
+
##### `health()`
|
|
181
|
+
|
|
182
|
+
Checks server health.
|
|
183
|
+
|
|
184
|
+
**Returns:** `Promise<HealthResponse>`
|
|
185
|
+
|
|
186
|
+
## TypeScript Types
|
|
187
|
+
|
|
188
|
+
All types are exported from the main package:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import {
|
|
192
|
+
RondevuClient,
|
|
193
|
+
Session,
|
|
194
|
+
TopicInfo,
|
|
195
|
+
CreateOfferRequest,
|
|
196
|
+
AnswerRequest,
|
|
197
|
+
PollRequest,
|
|
198
|
+
Side,
|
|
199
|
+
// ... and more
|
|
200
|
+
} from '@xtr-dev/rondevu-client';
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Node.js Usage
|
|
204
|
+
|
|
205
|
+
For Node.js environments (v18+), the built-in fetch is used automatically. For older Node.js versions, provide a fetch implementation:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import fetch from 'node-fetch';
|
|
209
|
+
import { RondevuClient } from '@xtr-dev/rondevu-client';
|
|
210
|
+
|
|
211
|
+
const client = new RondevuClient({
|
|
212
|
+
baseUrl: 'https://rondevu.example.com',
|
|
213
|
+
fetch: fetch as any
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Error Handling
|
|
218
|
+
|
|
219
|
+
All API methods throw errors with descriptive messages:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
try {
|
|
223
|
+
await client.createOffer('my-room', {
|
|
224
|
+
info: 'peer-id',
|
|
225
|
+
offer: data
|
|
226
|
+
});
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('Failed to create offer:', error.message);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { RondevuClientOptions, ListTopicsResponse, ListSessionsResponse, CreateOfferRequest, CreateOfferResponse, AnswerRequest, AnswerResponse, PollOffererResponse, PollAnswererResponse, HealthResponse, Side } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP client for Rondevu peer signaling and discovery server
|
|
4
|
+
*/
|
|
5
|
+
export declare class RondevuClient {
|
|
6
|
+
private readonly baseUrl;
|
|
7
|
+
private readonly origin;
|
|
8
|
+
private readonly fetchImpl;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new Rondevu client instance
|
|
11
|
+
* @param options - Client configuration options
|
|
12
|
+
*/
|
|
13
|
+
constructor(options: RondevuClientOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Makes an HTTP request to the Rondevu server
|
|
16
|
+
*/
|
|
17
|
+
private request;
|
|
18
|
+
/**
|
|
19
|
+
* Lists all topics with peer counts
|
|
20
|
+
*
|
|
21
|
+
* @param page - Page number (starting from 1)
|
|
22
|
+
* @param limit - Results per page (max 1000)
|
|
23
|
+
* @returns List of topics with pagination info
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
28
|
+
* const { topics, pagination } = await client.listTopics();
|
|
29
|
+
* console.log(`Found ${topics.length} topics`);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
listTopics(page?: number, limit?: number): Promise<ListTopicsResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Discovers available peers for a given topic
|
|
35
|
+
*
|
|
36
|
+
* @param topic - Topic identifier
|
|
37
|
+
* @returns List of available sessions
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
42
|
+
* const { sessions } = await client.listSessions('my-room');
|
|
43
|
+
* const otherPeers = sessions.filter(s => s.info !== myPeerId);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
listSessions(topic: string): Promise<ListSessionsResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* Announces peer availability and creates a new session
|
|
49
|
+
*
|
|
50
|
+
* @param topic - Topic identifier for grouping peers (max 256 characters)
|
|
51
|
+
* @param request - Offer details including peer info and signaling data
|
|
52
|
+
* @returns Unique session code (UUID)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
57
|
+
* const { code } = await client.createOffer('my-room', {
|
|
58
|
+
* info: 'peer-123',
|
|
59
|
+
* offer: signalingData
|
|
60
|
+
* });
|
|
61
|
+
* console.log('Session code:', code);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
createOffer(topic: string, request: CreateOfferRequest): Promise<CreateOfferResponse>;
|
|
65
|
+
/**
|
|
66
|
+
* Sends an answer or candidate to an existing session
|
|
67
|
+
*
|
|
68
|
+
* @param request - Answer details including session code and signaling data
|
|
69
|
+
* @returns Success confirmation
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
74
|
+
*
|
|
75
|
+
* // Send answer
|
|
76
|
+
* await client.sendAnswer({
|
|
77
|
+
* code: sessionCode,
|
|
78
|
+
* answer: answerData,
|
|
79
|
+
* side: 'answerer'
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* // Send candidate
|
|
83
|
+
* await client.sendAnswer({
|
|
84
|
+
* code: sessionCode,
|
|
85
|
+
* candidate: candidateData,
|
|
86
|
+
* side: 'offerer'
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
sendAnswer(request: AnswerRequest): Promise<AnswerResponse>;
|
|
91
|
+
/**
|
|
92
|
+
* Polls for session data from the other peer
|
|
93
|
+
*
|
|
94
|
+
* @param code - Session UUID
|
|
95
|
+
* @param side - Which side is polling ('offerer' or 'answerer')
|
|
96
|
+
* @returns Session data including offers, answers, and candidates
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
101
|
+
*
|
|
102
|
+
* // Offerer polls for answer
|
|
103
|
+
* const offererData = await client.poll(sessionCode, 'offerer');
|
|
104
|
+
* if (offererData.answer) {
|
|
105
|
+
* console.log('Received answer:', offererData.answer);
|
|
106
|
+
* }
|
|
107
|
+
*
|
|
108
|
+
* // Answerer polls for offer
|
|
109
|
+
* const answererData = await client.poll(sessionCode, 'answerer');
|
|
110
|
+
* console.log('Received offer:', answererData.offer);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
poll(code: string, side: Side): Promise<PollOffererResponse | PollAnswererResponse>;
|
|
114
|
+
/**
|
|
115
|
+
* Checks server health
|
|
116
|
+
*
|
|
117
|
+
* @returns Health status and timestamp
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
122
|
+
* const health = await client.health();
|
|
123
|
+
* console.log('Server status:', health.status);
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
health(): Promise<HealthResponse>;
|
|
127
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RondevuClient = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* HTTP client for Rondevu peer signaling and discovery server
|
|
6
|
+
*/
|
|
7
|
+
class RondevuClient {
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new Rondevu client instance
|
|
10
|
+
* @param options - Client configuration options
|
|
11
|
+
*/
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
14
|
+
this.origin = options.origin || new URL(this.baseUrl).origin;
|
|
15
|
+
this.fetchImpl = options.fetch || fetch;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Makes an HTTP request to the Rondevu server
|
|
19
|
+
*/
|
|
20
|
+
async request(endpoint, options = {}) {
|
|
21
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
22
|
+
const headers = {
|
|
23
|
+
'Origin': this.origin,
|
|
24
|
+
...options.headers,
|
|
25
|
+
};
|
|
26
|
+
if (options.body) {
|
|
27
|
+
headers['Content-Type'] = 'application/json';
|
|
28
|
+
}
|
|
29
|
+
const response = await this.fetchImpl(url, {
|
|
30
|
+
...options,
|
|
31
|
+
headers,
|
|
32
|
+
});
|
|
33
|
+
const data = await response.json();
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
const error = data;
|
|
36
|
+
throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Lists all topics with peer counts
|
|
42
|
+
*
|
|
43
|
+
* @param page - Page number (starting from 1)
|
|
44
|
+
* @param limit - Results per page (max 1000)
|
|
45
|
+
* @returns List of topics with pagination info
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
50
|
+
* const { topics, pagination } = await client.listTopics();
|
|
51
|
+
* console.log(`Found ${topics.length} topics`);
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
async listTopics(page = 1, limit = 100) {
|
|
55
|
+
const params = new URLSearchParams({
|
|
56
|
+
page: page.toString(),
|
|
57
|
+
limit: limit.toString(),
|
|
58
|
+
});
|
|
59
|
+
return this.request(`/?${params}`, {
|
|
60
|
+
method: 'GET',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Discovers available peers for a given topic
|
|
65
|
+
*
|
|
66
|
+
* @param topic - Topic identifier
|
|
67
|
+
* @returns List of available sessions
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
72
|
+
* const { sessions } = await client.listSessions('my-room');
|
|
73
|
+
* const otherPeers = sessions.filter(s => s.info !== myPeerId);
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
async listSessions(topic) {
|
|
77
|
+
return this.request(`/${encodeURIComponent(topic)}/sessions`, {
|
|
78
|
+
method: 'GET',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Announces peer availability and creates a new session
|
|
83
|
+
*
|
|
84
|
+
* @param topic - Topic identifier for grouping peers (max 256 characters)
|
|
85
|
+
* @param request - Offer details including peer info and signaling data
|
|
86
|
+
* @returns Unique session code (UUID)
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
91
|
+
* const { code } = await client.createOffer('my-room', {
|
|
92
|
+
* info: 'peer-123',
|
|
93
|
+
* offer: signalingData
|
|
94
|
+
* });
|
|
95
|
+
* console.log('Session code:', code);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
async createOffer(topic, request) {
|
|
99
|
+
return this.request(`/${encodeURIComponent(topic)}/offer`, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
body: JSON.stringify(request),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Sends an answer or candidate to an existing session
|
|
106
|
+
*
|
|
107
|
+
* @param request - Answer details including session code and signaling data
|
|
108
|
+
* @returns Success confirmation
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
113
|
+
*
|
|
114
|
+
* // Send answer
|
|
115
|
+
* await client.sendAnswer({
|
|
116
|
+
* code: sessionCode,
|
|
117
|
+
* answer: answerData,
|
|
118
|
+
* side: 'answerer'
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* // Send candidate
|
|
122
|
+
* await client.sendAnswer({
|
|
123
|
+
* code: sessionCode,
|
|
124
|
+
* candidate: candidateData,
|
|
125
|
+
* side: 'offerer'
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
async sendAnswer(request) {
|
|
130
|
+
return this.request('/answer', {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
body: JSON.stringify(request),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Polls for session data from the other peer
|
|
137
|
+
*
|
|
138
|
+
* @param code - Session UUID
|
|
139
|
+
* @param side - Which side is polling ('offerer' or 'answerer')
|
|
140
|
+
* @returns Session data including offers, answers, and candidates
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
145
|
+
*
|
|
146
|
+
* // Offerer polls for answer
|
|
147
|
+
* const offererData = await client.poll(sessionCode, 'offerer');
|
|
148
|
+
* if (offererData.answer) {
|
|
149
|
+
* console.log('Received answer:', offererData.answer);
|
|
150
|
+
* }
|
|
151
|
+
*
|
|
152
|
+
* // Answerer polls for offer
|
|
153
|
+
* const answererData = await client.poll(sessionCode, 'answerer');
|
|
154
|
+
* console.log('Received offer:', answererData.offer);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
async poll(code, side) {
|
|
158
|
+
const request = { code, side };
|
|
159
|
+
return this.request('/poll', {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
body: JSON.stringify(request),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Checks server health
|
|
166
|
+
*
|
|
167
|
+
* @returns Health status and timestamp
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
|
172
|
+
* const health = await client.health();
|
|
173
|
+
* console.log('Server status:', health.status);
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
async health() {
|
|
177
|
+
return this.request('/health', {
|
|
178
|
+
method: 'GET',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.RondevuClient = RondevuClient;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript client for Rondevu peer signaling server
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { RondevuClient } from '@xtr-dev/rondevu-client';
|
|
7
|
+
*
|
|
8
|
+
* const client = new RondevuClient({
|
|
9
|
+
* baseUrl: 'https://rondevu.example.com'
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* // Create an offer
|
|
13
|
+
* const { code } = await client.createOffer('my-room', {
|
|
14
|
+
* info: 'peer-123',
|
|
15
|
+
* offer: signalingData
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Discover peers
|
|
19
|
+
* const { sessions } = await client.listSessions('my-room');
|
|
20
|
+
*
|
|
21
|
+
* // Send answer
|
|
22
|
+
* await client.sendAnswer({
|
|
23
|
+
* code: sessions[0].code,
|
|
24
|
+
* answer: answerData,
|
|
25
|
+
* side: 'answerer'
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export { RondevuClient } from './client';
|
|
30
|
+
export * from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TypeScript client for Rondevu peer signaling server
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { RondevuClient } from '@xtr-dev/rondevu-client';
|
|
8
|
+
*
|
|
9
|
+
* const client = new RondevuClient({
|
|
10
|
+
* baseUrl: 'https://rondevu.example.com'
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // Create an offer
|
|
14
|
+
* const { code } = await client.createOffer('my-room', {
|
|
15
|
+
* info: 'peer-123',
|
|
16
|
+
* offer: signalingData
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Discover peers
|
|
20
|
+
* const { sessions } = await client.listSessions('my-room');
|
|
21
|
+
*
|
|
22
|
+
* // Send answer
|
|
23
|
+
* await client.sendAnswer({
|
|
24
|
+
* code: sessions[0].code,
|
|
25
|
+
* answer: answerData,
|
|
26
|
+
* side: 'answerer'
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
33
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
34
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperty(o, k2, desc);
|
|
37
|
+
}) : (function(o, m, k, k2) {
|
|
38
|
+
if (k2 === undefined) k2 = k;
|
|
39
|
+
o[k2] = m[k];
|
|
40
|
+
}));
|
|
41
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
42
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.RondevuClient = void 0;
|
|
46
|
+
var client_1 = require("./client");
|
|
47
|
+
Object.defineProperty(exports, "RondevuClient", { enumerable: true, get: function () { return client_1.RondevuClient; } });
|
|
48
|
+
__exportStar(require("./types"), exports);
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session side - identifies which peer in a connection
|
|
3
|
+
*/
|
|
4
|
+
export type Side = 'offerer' | 'answerer';
|
|
5
|
+
/**
|
|
6
|
+
* Session information returned from discovery endpoints
|
|
7
|
+
*/
|
|
8
|
+
export interface Session {
|
|
9
|
+
/** Unique session identifier (UUID) */
|
|
10
|
+
code: string;
|
|
11
|
+
/** Peer identifier/metadata */
|
|
12
|
+
info: string;
|
|
13
|
+
/** Signaling data for peer connection */
|
|
14
|
+
offer: string;
|
|
15
|
+
/** Additional signaling data from offerer */
|
|
16
|
+
offerCandidates: string[];
|
|
17
|
+
/** Unix timestamp when session was created */
|
|
18
|
+
createdAt: number;
|
|
19
|
+
/** Unix timestamp when session expires */
|
|
20
|
+
expiresAt: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Topic information with peer count
|
|
24
|
+
*/
|
|
25
|
+
export interface TopicInfo {
|
|
26
|
+
/** Topic identifier */
|
|
27
|
+
topic: string;
|
|
28
|
+
/** Number of available peers in this topic */
|
|
29
|
+
count: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Pagination information
|
|
33
|
+
*/
|
|
34
|
+
export interface Pagination {
|
|
35
|
+
/** Current page number */
|
|
36
|
+
page: number;
|
|
37
|
+
/** Results per page */
|
|
38
|
+
limit: number;
|
|
39
|
+
/** Total number of results */
|
|
40
|
+
total: number;
|
|
41
|
+
/** Whether there are more results available */
|
|
42
|
+
hasMore: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Response from GET / - list all topics
|
|
46
|
+
*/
|
|
47
|
+
export interface ListTopicsResponse {
|
|
48
|
+
topics: TopicInfo[];
|
|
49
|
+
pagination: Pagination;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Response from GET /:topic/sessions - list sessions in a topic
|
|
53
|
+
*/
|
|
54
|
+
export interface ListSessionsResponse {
|
|
55
|
+
sessions: Session[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Request body for POST /:topic/offer
|
|
59
|
+
*/
|
|
60
|
+
export interface CreateOfferRequest {
|
|
61
|
+
/** Peer identifier/metadata (max 1024 characters) */
|
|
62
|
+
info: string;
|
|
63
|
+
/** Signaling data for peer connection */
|
|
64
|
+
offer: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Response from POST /:topic/offer
|
|
68
|
+
*/
|
|
69
|
+
export interface CreateOfferResponse {
|
|
70
|
+
/** Unique session identifier (UUID) */
|
|
71
|
+
code: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Request body for POST /answer
|
|
75
|
+
*/
|
|
76
|
+
export interface AnswerRequest {
|
|
77
|
+
/** Session UUID from the offer */
|
|
78
|
+
code: string;
|
|
79
|
+
/** Response signaling data (required if candidate not provided) */
|
|
80
|
+
answer?: string;
|
|
81
|
+
/** Additional signaling data (required if answer not provided) */
|
|
82
|
+
candidate?: string;
|
|
83
|
+
/** Which peer is sending the data */
|
|
84
|
+
side: Side;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Response from POST /answer
|
|
88
|
+
*/
|
|
89
|
+
export interface AnswerResponse {
|
|
90
|
+
success: boolean;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Request body for POST /poll
|
|
94
|
+
*/
|
|
95
|
+
export interface PollRequest {
|
|
96
|
+
/** Session UUID */
|
|
97
|
+
code: string;
|
|
98
|
+
/** Which side is polling */
|
|
99
|
+
side: Side;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Response from POST /poll when side=offerer
|
|
103
|
+
*/
|
|
104
|
+
export interface PollOffererResponse {
|
|
105
|
+
/** Answer from answerer (null if not yet received) */
|
|
106
|
+
answer: string | null;
|
|
107
|
+
/** Additional signaling data from answerer */
|
|
108
|
+
answerCandidates: string[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Response from POST /poll when side=answerer
|
|
112
|
+
*/
|
|
113
|
+
export interface PollAnswererResponse {
|
|
114
|
+
/** Offer from offerer */
|
|
115
|
+
offer: string;
|
|
116
|
+
/** Additional signaling data from offerer */
|
|
117
|
+
offerCandidates: string[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Response from POST /poll (union type)
|
|
121
|
+
*/
|
|
122
|
+
export type PollResponse = PollOffererResponse | PollAnswererResponse;
|
|
123
|
+
/**
|
|
124
|
+
* Response from GET /health
|
|
125
|
+
*/
|
|
126
|
+
export interface HealthResponse {
|
|
127
|
+
status: 'ok';
|
|
128
|
+
timestamp: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Error response structure
|
|
132
|
+
*/
|
|
133
|
+
export interface ErrorResponse {
|
|
134
|
+
error: string;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Client configuration options
|
|
138
|
+
*/
|
|
139
|
+
export interface RondevuClientOptions {
|
|
140
|
+
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
|
141
|
+
baseUrl: string;
|
|
142
|
+
/** Origin header value for session isolation (defaults to baseUrl origin) */
|
|
143
|
+
origin?: string;
|
|
144
|
+
/** Optional fetch implementation (for Node.js environments) */
|
|
145
|
+
fetch?: typeof fetch;
|
|
146
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xtr-dev/rondevu-client",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TypeScript client for Rondevu peer signaling and discovery server",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"typecheck": "tsc --noEmit",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"webrtc",
|
|
14
|
+
"p2p",
|
|
15
|
+
"signaling",
|
|
16
|
+
"peer-discovery",
|
|
17
|
+
"rondevu"
|
|
18
|
+
],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.9.3"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
]
|
|
28
|
+
}
|