mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 10:53:24 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b6129294c4 | |||
| 649a8d5d3f | |||
| 2065aecc6a | |||
| 5e98610e30 | |||
| 2c3f8ef22b | |||
| 7831e03af1 | |||
| 9df9966381 | |||
| de6244cf24 | |||
| 33ecb9f9bc |
28
README.md
28
README.md
@@ -1,12 +1,20 @@
|
|||||||
# Rondevu
|
# Rondevu
|
||||||
|
|
||||||
🎯 Meet WebRTC peers by topic, by peer ID, or by connection ID.
|
🎯 **Simple WebRTC peer signaling and discovery**
|
||||||
|
|
||||||
|
Meet peers by topic, by peer ID, or by connection ID.
|
||||||
|
|
||||||
|
**Related repositories:**
|
||||||
|
- [rondevu-server](https://github.com/xtr-dev/rondevu-server) - HTTP signaling server
|
||||||
|
- [rondevu-demo](https://github.com/xtr-dev/rondevu-demo) - Interactive demo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## @xtr-dev/rondevu-client
|
## @xtr-dev/rondevu-client
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/@xtr-dev/rondevu-client)
|
[](https://www.npmjs.com/package/@xtr-dev/rondevu-client)
|
||||||
|
|
||||||
TypeScript Rondevu HTTP and WebRTC client, for simple peer discovery and connection.
|
TypeScript client library for Rondevu peer signaling and WebRTC connection management. Handles automatic signaling, ICE candidate exchange, and connection establishment.
|
||||||
|
|
||||||
### Install
|
### Install
|
||||||
|
|
||||||
@@ -19,7 +27,21 @@ npm install @xtr-dev/rondevu-client
|
|||||||
```typescript
|
```typescript
|
||||||
import { Rondevu } from '@xtr-dev/rondevu-client';
|
import { Rondevu } from '@xtr-dev/rondevu-client';
|
||||||
|
|
||||||
const rdv = new Rondevu({ baseUrl: 'https://server.com' });
|
const rdv = new Rondevu({
|
||||||
|
baseUrl: 'https://server.com',
|
||||||
|
rtcConfig: {
|
||||||
|
iceServers: [
|
||||||
|
// your ICE servers here
|
||||||
|
{ urls: 'stun:stun.l.google.com:19302' },
|
||||||
|
{ urls: 'stun:stun1.l.google.com:19302' },
|
||||||
|
{
|
||||||
|
urls: 'turn:relay1.example.com:3480',
|
||||||
|
username: 'example',
|
||||||
|
credential: 'example'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Connect by topic
|
// Connect by topic
|
||||||
const conn = await rdv.join('room');
|
const conn = await rdv.join('room');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/rondevu-client",
|
"name": "@xtr-dev/rondevu-client",
|
||||||
"version": "0.0.4",
|
"version": "0.1.1",
|
||||||
"description": "TypeScript client for Rondevu peer signaling and discovery server",
|
"description": "TypeScript client for Rondevu peer signaling and discovery server",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build",
|
||||||
|
"publish": "npm publish"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"webrtc",
|
"webrtc",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
PollRequest,
|
PollRequest,
|
||||||
PollOffererResponse,
|
PollOffererResponse,
|
||||||
PollAnswererResponse,
|
PollAnswererResponse,
|
||||||
|
VersionResponse,
|
||||||
HealthResponse,
|
HealthResponse,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
Side,
|
Side,
|
||||||
@@ -19,7 +20,6 @@ import {
|
|||||||
*/
|
*/
|
||||||
export class RondevuClient {
|
export class RondevuClient {
|
||||||
private readonly baseUrl: string;
|
private readonly baseUrl: string;
|
||||||
private readonly origin: string;
|
|
||||||
private readonly fetchImpl: typeof fetch;
|
private readonly fetchImpl: typeof fetch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +28,6 @@ export class RondevuClient {
|
|||||||
*/
|
*/
|
||||||
constructor(options: RondevuClientOptions) {
|
constructor(options: RondevuClientOptions) {
|
||||||
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
||||||
this.origin = options.origin || new URL(this.baseUrl).origin;
|
|
||||||
this.fetchImpl = options.fetch || globalThis.fetch.bind(globalThis);
|
this.fetchImpl = options.fetch || globalThis.fetch.bind(globalThis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ export class RondevuClient {
|
|||||||
const url = `${this.baseUrl}${endpoint}`;
|
const url = `${this.baseUrl}${endpoint}`;
|
||||||
|
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
'Origin': this.origin,
|
|
||||||
...(options.headers as Record<string, string>),
|
...(options.headers as Record<string, string>),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,6 +63,24 @@ export class RondevuClient {
|
|||||||
return data as T;
|
return data as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets server version information
|
||||||
|
*
|
||||||
|
* @returns Server version (git commit hash)
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
* const { version } = await client.getVersion();
|
||||||
|
* console.log('Server version:', version);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async getVersion(): Promise<VersionResponse> {
|
||||||
|
return this.request<VersionResponse>('/', {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all topics with peer counts
|
* Lists all topics with peer counts
|
||||||
*
|
*
|
||||||
@@ -84,7 +100,7 @@ export class RondevuClient {
|
|||||||
page: page.toString(),
|
page: page.toString(),
|
||||||
limit: limit.toString(),
|
limit: limit.toString(),
|
||||||
});
|
});
|
||||||
return this.request<ListTopicsResponse>(`/?${params}`, {
|
return this.request<ListTopicsResponse>(`/topics?${params}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export type {
|
|||||||
PollOffererResponse,
|
PollOffererResponse,
|
||||||
PollAnswererResponse,
|
PollAnswererResponse,
|
||||||
PollResponse,
|
PollResponse,
|
||||||
|
VersionResponse,
|
||||||
HealthResponse,
|
HealthResponse,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
RondevuClientOptions,
|
RondevuClientOptions,
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ export class Rondevu {
|
|||||||
readonly peerId: string;
|
readonly peerId: string;
|
||||||
|
|
||||||
private client: RondevuClient;
|
private client: RondevuClient;
|
||||||
|
private baseUrl: string;
|
||||||
|
private fetchImpl?: typeof fetch;
|
||||||
private rtcConfig?: RTCConfiguration;
|
private rtcConfig?: RTCConfiguration;
|
||||||
private pollingInterval: number;
|
private pollingInterval: number;
|
||||||
private connectionTimeout: number;
|
private connectionTimeout: number;
|
||||||
@@ -17,10 +19,12 @@ export class Rondevu {
|
|||||||
* Creates a new Rondevu client instance
|
* Creates a new Rondevu client instance
|
||||||
* @param options - Client configuration options
|
* @param options - Client configuration options
|
||||||
*/
|
*/
|
||||||
constructor(options: RondevuOptions) {
|
constructor(options: RondevuOptions = {}) {
|
||||||
|
this.baseUrl = options.baseUrl || 'https://rondevu.xtrdev.workers.dev';
|
||||||
|
this.fetchImpl = options.fetch;
|
||||||
|
|
||||||
this.client = new RondevuClient({
|
this.client = new RondevuClient({
|
||||||
baseUrl: options.baseUrl,
|
baseUrl: this.baseUrl,
|
||||||
origin: options.origin,
|
|
||||||
fetch: options.fetch,
|
fetch: options.fetch,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -99,7 +103,7 @@ export class Rondevu {
|
|||||||
*/
|
*/
|
||||||
async connect(id: string): Promise<RondevuConnection> {
|
async connect(id: string): Promise<RondevuConnection> {
|
||||||
// Poll server to get session by ID
|
// Poll server to get session by ID
|
||||||
const sessionData = await this.findSessionById(id);
|
const sessionData = await this.findSessionByIdWithClient(id, this.client);
|
||||||
|
|
||||||
if (!sessionData) {
|
if (!sessionData) {
|
||||||
throw new Error(`Connection ${id} not found or expired`);
|
throw new Error(`Connection ${id} not found or expired`);
|
||||||
@@ -237,7 +241,10 @@ export class Rondevu {
|
|||||||
* Find a session by connection ID
|
* Find a session by connection ID
|
||||||
* This requires polling since we don't know which topic it's in
|
* This requires polling since we don't know which topic it's in
|
||||||
*/
|
*/
|
||||||
private async findSessionById(id: string): Promise<{
|
private async findSessionByIdWithClient(
|
||||||
|
id: string,
|
||||||
|
client: RondevuClient
|
||||||
|
): Promise<{
|
||||||
code: string;
|
code: string;
|
||||||
peerId: string;
|
peerId: string;
|
||||||
offer: string;
|
offer: string;
|
||||||
@@ -246,7 +253,7 @@ export class Rondevu {
|
|||||||
try {
|
try {
|
||||||
// Try to poll for the session directly
|
// Try to poll for the session directly
|
||||||
// The poll endpoint should return the session data
|
// The poll endpoint should return the session data
|
||||||
const response = await this.client.poll(id, 'answerer');
|
const response = await client.poll(id, 'answerer');
|
||||||
const answererResponse = response as { offer: string; offerCandidates: string[] };
|
const answererResponse = response as { offer: string; offerCandidates: string[] };
|
||||||
|
|
||||||
if (answererResponse.offer) {
|
if (answererResponse.offer) {
|
||||||
|
|||||||
16
src/types.ts
16
src/types.ts
@@ -140,6 +140,14 @@ export interface PollAnswererResponse {
|
|||||||
*/
|
*/
|
||||||
export type PollResponse = PollOffererResponse | PollAnswererResponse;
|
export type PollResponse = PollOffererResponse | PollAnswererResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from GET / - server version information
|
||||||
|
*/
|
||||||
|
export interface VersionResponse {
|
||||||
|
/** Git commit hash or version identifier */
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response from GET /health
|
* Response from GET /health
|
||||||
*/
|
*/
|
||||||
@@ -161,8 +169,6 @@ export interface ErrorResponse {
|
|||||||
export interface RondevuClientOptions {
|
export interface RondevuClientOptions {
|
||||||
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
/** Origin header value for session isolation (defaults to baseUrl origin) */
|
|
||||||
origin?: string;
|
|
||||||
/** Optional fetch implementation (for Node.js environments) */
|
/** Optional fetch implementation (for Node.js environments) */
|
||||||
fetch?: typeof fetch;
|
fetch?: typeof fetch;
|
||||||
}
|
}
|
||||||
@@ -175,12 +181,10 @@ export interface RondevuClientOptions {
|
|||||||
* Configuration options for Rondevu WebRTC client
|
* Configuration options for Rondevu WebRTC client
|
||||||
*/
|
*/
|
||||||
export interface RondevuOptions {
|
export interface RondevuOptions {
|
||||||
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
/** Base URL of the Rondevu server (defaults to 'https://rondevu.xtrdev.workers.dev') */
|
||||||
baseUrl: string;
|
baseUrl?: string;
|
||||||
/** Peer identifier (optional, auto-generated if not provided) */
|
/** Peer identifier (optional, auto-generated if not provided) */
|
||||||
peerId?: string;
|
peerId?: string;
|
||||||
/** Origin header value for session isolation (defaults to baseUrl origin) */
|
|
||||||
origin?: string;
|
|
||||||
/** Optional fetch implementation (for Node.js environments) */
|
/** Optional fetch implementation (for Node.js environments) */
|
||||||
fetch?: typeof fetch;
|
fetch?: typeof fetch;
|
||||||
/** WebRTC configuration (ICE servers, etc.) */
|
/** WebRTC configuration (ICE servers, etc.) */
|
||||||
|
|||||||
Reference in New Issue
Block a user