Remove global origin option and update README

- Remove origin option from RondevuClientOptions and RondevuOptions
- Remove ConnectOptions interface with global flag
- Remove all customHeaders logic for origin override
- Update README with consistent Rondevu branding

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-08 10:52:56 +01:00
parent 7831e03af1
commit 2c3f8ef22b
5 changed files with 21 additions and 47 deletions

View File

@@ -1,12 +1,16 @@
# 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.
---
## @xtr-dev/rondevu-client ## @xtr-dev/rondevu-client
[![npm version](https://img.shields.io/npm/v/@xtr-dev/rondevu-client)](https://www.npmjs.com/package/@xtr-dev/rondevu-client) [![npm version](https://img.shields.io/npm/v/@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

View File

@@ -19,7 +19,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 +27,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);
} }
@@ -37,15 +35,12 @@ export class RondevuClient {
*/ */
private async request<T>( private async request<T>(
endpoint: string, endpoint: string,
options: RequestInit = {}, options: RequestInit = {}
customHeaders?: Record<string, string>
): Promise<T> { ): Promise<T> {
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>),
...(customHeaders || {}),
}; };
if (options.body) { if (options.body) {
@@ -144,7 +139,6 @@ export class RondevuClient {
* Sends an answer or candidate to an existing session * Sends an answer or candidate to an existing session
* *
* @param request - Answer details including session code and signaling data * @param request - Answer details including session code and signaling data
* @param customHeaders - Optional custom headers to send with the request
* @returns Success confirmation * @returns Success confirmation
* *
* @example * @example
@@ -166,11 +160,11 @@ export class RondevuClient {
* }); * });
* ``` * ```
*/ */
async sendAnswer(request: AnswerRequest, customHeaders?: Record<string, string>): Promise<AnswerResponse> { async sendAnswer(request: AnswerRequest): Promise<AnswerResponse> {
return this.request<AnswerResponse>('/answer', { return this.request<AnswerResponse>('/answer', {
method: 'POST', method: 'POST',
body: JSON.stringify(request), body: JSON.stringify(request),
}, customHeaders); });
} }
/** /**
@@ -178,7 +172,6 @@ export class RondevuClient {
* *
* @param code - Session UUID * @param code - Session UUID
* @param side - Which side is polling ('offerer' or 'answerer') * @param side - Which side is polling ('offerer' or 'answerer')
* @param customHeaders - Optional custom headers to send with the request
* @returns Session data including offers, answers, and candidates * @returns Session data including offers, answers, and candidates
* *
* @example * @example
@@ -198,14 +191,13 @@ export class RondevuClient {
*/ */
async poll( async poll(
code: string, code: string,
side: Side, side: Side
customHeaders?: Record<string, string>
): Promise<PollOffererResponse | PollAnswererResponse> { ): Promise<PollOffererResponse | PollAnswererResponse> {
const request: PollRequest = { code, side }; const request: PollRequest = { code, side };
return this.request<PollOffererResponse | PollAnswererResponse>('/poll', { return this.request<PollOffererResponse | PollAnswererResponse>('/poll', {
method: 'POST', method: 'POST',
body: JSON.stringify(request), body: JSON.stringify(request),
}, customHeaders); });
} }
/** /**

View File

@@ -21,9 +21,8 @@ export class RondevuConnection extends EventEmitter {
private connectionTimer?: ReturnType<typeof setTimeout>; private connectionTimer?: ReturnType<typeof setTimeout>;
private isPolling: boolean = false; private isPolling: boolean = false;
private isClosed: boolean = false; private isClosed: boolean = false;
private customHeaders?: Record<string, string>;
constructor(params: RondevuConnectionParams, client: RondevuClient, customHeaders?: Record<string, string>) { constructor(params: RondevuConnectionParams, client: RondevuClient) {
super(); super();
this.id = params.id; this.id = params.id;
this.topic = params.topic; this.topic = params.topic;
@@ -35,7 +34,6 @@ export class RondevuConnection extends EventEmitter {
this.dataChannels = new Map(); this.dataChannels = new Map();
this.pollingIntervalMs = params.pollingInterval; this.pollingIntervalMs = params.pollingInterval;
this.connectionTimeoutMs = params.connectionTimeout; this.connectionTimeoutMs = params.connectionTimeout;
this.customHeaders = customHeaders;
this.setupEventHandlers(); this.setupEventHandlers();
this.startConnectionTimeout(); this.startConnectionTimeout();
@@ -121,7 +119,7 @@ export class RondevuConnection extends EventEmitter {
code: this.id, code: this.id,
candidate: JSON.stringify(candidate.toJSON()), candidate: JSON.stringify(candidate.toJSON()),
side: this.role, side: this.role,
}, this.customHeaders); });
} catch (err: any) { } catch (err: any) {
throw new Error(`Failed to send ICE candidate: ${err.message}`); throw new Error(`Failed to send ICE candidate: ${err.message}`);
} }
@@ -171,7 +169,7 @@ export class RondevuConnection extends EventEmitter {
} }
try { try {
const response = await this.client.poll(this.id, this.role, this.customHeaders); const response = await this.client.poll(this.id, this.role);
if (this.role === 'offerer') { if (this.role === 'offerer') {
const offererResponse = response as { answer: string | null; answerCandidates: string[] }; const offererResponse = response as { answer: string | null; answerCandidates: string[] };

View File

@@ -1,6 +1,6 @@
import { RondevuClient } from './client'; import { RondevuClient } from './client';
import { RondevuConnection } from './connection'; import { RondevuConnection } from './connection';
import { RondevuOptions, JoinOptions, ConnectOptions, RondevuConnectionParams } from './types'; import { RondevuOptions, JoinOptions, RondevuConnectionParams } from './types';
/** /**
* Main Rondevu WebRTC client with automatic connection management * Main Rondevu WebRTC client with automatic connection management
@@ -25,7 +25,6 @@ export class Rondevu {
this.client = new RondevuClient({ this.client = new RondevuClient({
baseUrl: this.baseUrl, baseUrl: this.baseUrl,
origin: options.origin,
fetch: options.fetch, fetch: options.fetch,
}); });
@@ -100,17 +99,11 @@ export class Rondevu {
/** /**
* Connect to an existing connection by ID (answerer role) * Connect to an existing connection by ID (answerer role)
* @param id - Connection identifier * @param id - Connection identifier
* @param options - Optional connection options (e.g., { global: true } for global origin)
* @returns Promise that resolves to RondevuConnection * @returns Promise that resolves to RondevuConnection
*/ */
async connect(id: string, options?: ConnectOptions): Promise<RondevuConnection> { async connect(id: string): Promise<RondevuConnection> {
// Build custom headers if global option is set
const customHeaders = options?.global
? { 'X-Rondevu-Global': 'true' }
: undefined;
// Poll server to get session by ID // Poll server to get session by ID
const sessionData = await this.findSessionByIdWithClient(id, this.client, customHeaders); 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`);
@@ -137,7 +130,7 @@ export class Rondevu {
code: id, code: id,
answer: pc.localDescription!.sdp, answer: pc.localDescription!.sdp,
side: 'answerer', side: 'answerer',
}, customHeaders); });
// Create connection object // Create connection object
const connectionParams: RondevuConnectionParams = { const connectionParams: RondevuConnectionParams = {
@@ -151,7 +144,7 @@ export class Rondevu {
connectionTimeout: this.connectionTimeout, connectionTimeout: this.connectionTimeout,
}; };
const connection = new RondevuConnection(connectionParams, this.client, customHeaders); const connection = new RondevuConnection(connectionParams, this.client);
// Start polling for ICE candidates // Start polling for ICE candidates
connection.startPolling(); connection.startPolling();
@@ -250,8 +243,7 @@ export class Rondevu {
*/ */
private async findSessionByIdWithClient( private async findSessionByIdWithClient(
id: string, id: string,
client: RondevuClient, client: RondevuClient
customHeaders?: Record<string, string>
): Promise<{ ): Promise<{
code: string; code: string;
peerId: string; peerId: string;
@@ -261,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 client.poll(id, 'answerer', customHeaders); 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) {

View File

@@ -161,8 +161,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;
} }
@@ -179,8 +177,6 @@ export interface RondevuOptions {
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.) */
@@ -191,14 +187,6 @@ export interface RondevuOptions {
connectionTimeout?: number; connectionTimeout?: number;
} }
/**
* Options for connecting to a session
*/
export interface ConnectOptions {
/** Use global origin (https://ronde.vu) instead of request origin for session isolation */
global?: boolean;
}
/** /**
* Options for joining a topic * Options for joining a topic
*/ */