mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 02:43:25 +00:00
Remove unused code (legacy files and heartbeat method)
- Removed unused legacy files: client.ts and types.ts (old API) - Removed heartbeat() method from offers API (doesn't actually reset TTL) - Removed heartbeat() documentation from README - Server only uses expires_at for cleanup, last_seen is never checked - Offers expire purely based on their original TTL 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -418,13 +418,6 @@ Get all offers owned by the authenticated peer.
|
|||||||
const myOffers = await client.offers.getMine();
|
const myOffers = await client.offers.getMine();
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `client.offers.heartbeat(offerId)`
|
|
||||||
Update last_seen timestamp for an offer.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
await client.offers.heartbeat(offerId);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `client.offers.delete(offerId)`
|
#### `client.offers.delete(offerId)`
|
||||||
Delete a specific offer.
|
Delete a specific offer.
|
||||||
|
|
||||||
|
|||||||
208
src/client.ts
208
src/client.ts
@@ -1,208 +0,0 @@
|
|||||||
import {
|
|
||||||
RondevuClientOptions,
|
|
||||||
CreateOfferRequest,
|
|
||||||
CreateOfferResponse,
|
|
||||||
AnswerRequest,
|
|
||||||
AnswerResponse,
|
|
||||||
PollRequest,
|
|
||||||
PollOffererResponse,
|
|
||||||
PollAnswererResponse,
|
|
||||||
VersionResponse,
|
|
||||||
HealthResponse,
|
|
||||||
ErrorResponse,
|
|
||||||
Side,
|
|
||||||
} from './types.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP API client for Rondevu peer signaling server
|
|
||||||
*/
|
|
||||||
export class RondevuAPI {
|
|
||||||
private readonly baseUrl: string;
|
|
||||||
private readonly fetchImpl: typeof fetch;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Rondevu API client instance
|
|
||||||
* @param options - Client configuration options
|
|
||||||
*/
|
|
||||||
constructor(options: RondevuClientOptions) {
|
|
||||||
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
||||||
this.fetchImpl = options.fetch || globalThis.fetch.bind(globalThis);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes an HTTP request to the Rondevu server
|
|
||||||
*/
|
|
||||||
private async request<T>(
|
|
||||||
endpoint: string,
|
|
||||||
options: RequestInit = {}
|
|
||||||
): Promise<T> {
|
|
||||||
const url = `${this.baseUrl}${endpoint}`;
|
|
||||||
|
|
||||||
const headers: Record<string, string> = {
|
|
||||||
...(options.headers as Record<string, string>),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.body) {
|
|
||||||
headers['Content-Type'] = 'application/json';
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.fetchImpl(url, {
|
|
||||||
...options,
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const error = data as ErrorResponse;
|
|
||||||
throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets server version information
|
|
||||||
*
|
|
||||||
* @returns Server version
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
* const { version } = await api.getVersion();
|
|
||||||
* console.log('Server version:', version);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async getVersion(): Promise<VersionResponse> {
|
|
||||||
return this.request<VersionResponse>('/', {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new offer
|
|
||||||
*
|
|
||||||
* @param request - Offer details including peer ID, signaling data, and optional custom code
|
|
||||||
* @returns Unique offer code (UUID or custom code)
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
* const { code } = await api.createOffer({
|
|
||||||
* peerId: 'peer-123',
|
|
||||||
* offer: signalingData,
|
|
||||||
* code: 'my-custom-code' // optional
|
|
||||||
* });
|
|
||||||
* console.log('Offer code:', code);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async createOffer(request: CreateOfferRequest): Promise<CreateOfferResponse> {
|
|
||||||
return this.request<CreateOfferResponse>('/offer', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(request),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends an answer or candidate to an existing offer
|
|
||||||
*
|
|
||||||
* @param request - Answer details including offer code and signaling data
|
|
||||||
* @returns Success confirmation
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
*
|
|
||||||
* // Send answer
|
|
||||||
* await api.sendAnswer({
|
|
||||||
* code: offerCode,
|
|
||||||
* answer: answerData,
|
|
||||||
* side: 'answerer'
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* // Send candidate
|
|
||||||
* await api.sendAnswer({
|
|
||||||
* code: offerCode,
|
|
||||||
* candidate: candidateData,
|
|
||||||
* side: 'offerer'
|
|
||||||
* });
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async sendAnswer(request: AnswerRequest): Promise<AnswerResponse> {
|
|
||||||
return this.request<AnswerResponse>('/answer', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(request),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Polls for offer data from the other peer
|
|
||||||
*
|
|
||||||
* @param code - Offer code
|
|
||||||
* @param side - Which side is polling ('offerer' or 'answerer')
|
|
||||||
* @returns Offer data including offers, answers, and candidates
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
*
|
|
||||||
* // Offerer polls for answer
|
|
||||||
* const offererData = await api.poll(offerCode, 'offerer');
|
|
||||||
* if (offererData.answer) {
|
|
||||||
* console.log('Received answer:', offererData.answer);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // Answerer polls for offer
|
|
||||||
* const answererData = await api.poll(offerCode, 'answerer');
|
|
||||||
* console.log('Received offer:', answererData.offer);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async poll(
|
|
||||||
code: string,
|
|
||||||
side: Side
|
|
||||||
): Promise<PollOffererResponse | PollAnswererResponse> {
|
|
||||||
const request: PollRequest = { code, side };
|
|
||||||
return this.request<PollOffererResponse | PollAnswererResponse>('/poll', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(request),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks server health and version
|
|
||||||
*
|
|
||||||
* @returns Health status, timestamp, and version
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
* const health = await api.health();
|
|
||||||
* console.log('Server status:', health.status);
|
|
||||||
* console.log('Server version:', health.version);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async health(): Promise<HealthResponse> {
|
|
||||||
return this.request<HealthResponse>('/health', {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends a session by deleting the offer from the server
|
|
||||||
*
|
|
||||||
* @param code - The offer code
|
|
||||||
* @returns Success confirmation
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```typescript
|
|
||||||
* const api = new RondevuAPI({ baseUrl: 'https://example.com' });
|
|
||||||
* await api.leave('my-offer-code');
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
async leave(code: string): Promise<{ success: boolean }> {
|
|
||||||
return this.request<{ success: boolean }>('/leave', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({ code }),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -195,23 +195,6 @@ export class RondevuOffers {
|
|||||||
return data.offers;
|
return data.offers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update offer heartbeat
|
|
||||||
*/
|
|
||||||
async heartbeat(offerId: string): Promise<void> {
|
|
||||||
const response = await this.fetchFn(`${this.baseUrl}/offers/${encodeURIComponent(offerId)}/heartbeat`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
Authorization: RondevuAuth.createAuthHeader(this.credentials),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
||||||
throw new Error(`Failed to update heartbeat: ${error.error || response.statusText}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an offer
|
* Delete an offer
|
||||||
*/
|
*/
|
||||||
|
|||||||
182
src/types.ts
182
src/types.ts
@@ -1,182 +0,0 @@
|
|||||||
// ============================================================================
|
|
||||||
// Signaling Types
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session side - identifies which peer in a connection
|
|
||||||
*/
|
|
||||||
export type Side = 'offerer' | 'answerer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request body for POST /offer
|
|
||||||
*/
|
|
||||||
export interface CreateOfferRequest {
|
|
||||||
/** Peer identifier/metadata (max 1024 characters) */
|
|
||||||
peerId: string;
|
|
||||||
/** Signaling data for peer connection */
|
|
||||||
offer: string;
|
|
||||||
/** Optional custom connection code (if not provided, server generates UUID) */
|
|
||||||
code?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response from POST /offer
|
|
||||||
*/
|
|
||||||
export interface CreateOfferResponse {
|
|
||||||
/** Unique session identifier (UUID) */
|
|
||||||
code: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request body for POST /answer
|
|
||||||
*/
|
|
||||||
export interface AnswerRequest {
|
|
||||||
/** Session UUID from the offer */
|
|
||||||
code: string;
|
|
||||||
/** Response signaling data (required if candidate not provided) */
|
|
||||||
answer?: string;
|
|
||||||
/** Additional signaling data (required if answer not provided) */
|
|
||||||
candidate?: string;
|
|
||||||
/** Which peer is sending the data */
|
|
||||||
side: Side;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response from POST /answer
|
|
||||||
*/
|
|
||||||
export interface AnswerResponse {
|
|
||||||
success: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request body for POST /poll
|
|
||||||
*/
|
|
||||||
export interface PollRequest {
|
|
||||||
/** Session UUID */
|
|
||||||
code: string;
|
|
||||||
/** Which side is polling */
|
|
||||||
side: Side;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response from POST /poll when side=offerer
|
|
||||||
*/
|
|
||||||
export interface PollOffererResponse {
|
|
||||||
/** Answer from answerer (null if not yet received) */
|
|
||||||
answer: string | null;
|
|
||||||
/** Additional signaling data from answerer */
|
|
||||||
answerCandidates: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response from POST /poll when side=answerer
|
|
||||||
*/
|
|
||||||
export interface PollAnswererResponse {
|
|
||||||
/** Offer from offerer */
|
|
||||||
offer: string;
|
|
||||||
/** Additional signaling data from offerer */
|
|
||||||
offerCandidates: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response from POST /poll (union type)
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
export interface HealthResponse {
|
|
||||||
status: 'ok';
|
|
||||||
timestamp: number;
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Error response structure
|
|
||||||
*/
|
|
||||||
export interface ErrorResponse {
|
|
||||||
error: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client configuration options
|
|
||||||
*/
|
|
||||||
export interface RondevuClientOptions {
|
|
||||||
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
|
||||||
baseUrl: string;
|
|
||||||
/** Optional fetch implementation (for Node.js environments) */
|
|
||||||
fetch?: typeof fetch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// WebRTC Types
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebRTC polyfill for Node.js and other non-browser platforms
|
|
||||||
*/
|
|
||||||
export interface WebRTCPolyfill {
|
|
||||||
RTCPeerConnection: typeof RTCPeerConnection;
|
|
||||||
RTCSessionDescription: typeof RTCSessionDescription;
|
|
||||||
RTCIceCandidate: typeof RTCIceCandidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration options for Rondevu WebRTC client
|
|
||||||
*/
|
|
||||||
export interface RondevuOptions {
|
|
||||||
/** Base URL of the Rondevu server (defaults to 'https://api.ronde.vu') */
|
|
||||||
baseUrl?: string;
|
|
||||||
/** Peer identifier (optional, auto-generated if not provided) */
|
|
||||||
peerId?: string;
|
|
||||||
/** Optional fetch implementation (for Node.js environments) */
|
|
||||||
fetch?: typeof fetch;
|
|
||||||
/** WebRTC configuration (ICE servers, etc.) */
|
|
||||||
rtcConfig?: RTCConfiguration;
|
|
||||||
/** Polling interval in milliseconds (default: 1000) */
|
|
||||||
pollingInterval?: number;
|
|
||||||
/** Connection timeout in milliseconds (default: 30000) */
|
|
||||||
connectionTimeout?: number;
|
|
||||||
/** WebRTC polyfill for Node.js (e.g., wrtc or @roamhq/wrtc) */
|
|
||||||
wrtc?: WebRTCPolyfill;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection role - whether this peer is creating or answering
|
|
||||||
*/
|
|
||||||
export type ConnectionRole = 'offerer' | 'answerer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters for creating a RondevuConnection
|
|
||||||
*/
|
|
||||||
export interface RondevuConnectionParams {
|
|
||||||
id: string;
|
|
||||||
topic?: string;
|
|
||||||
role: ConnectionRole;
|
|
||||||
pc: RTCPeerConnection;
|
|
||||||
localPeerId: string;
|
|
||||||
remotePeerId: string;
|
|
||||||
pollingInterval: number;
|
|
||||||
connectionTimeout: number;
|
|
||||||
wrtc?: WebRTCPolyfill;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event map for RondevuConnection events
|
|
||||||
*/
|
|
||||||
export interface RondevuConnectionEvents {
|
|
||||||
connect: () => void;
|
|
||||||
disconnect: () => void;
|
|
||||||
error: (error: Error) => void;
|
|
||||||
datachannel: (channel: RTCDataChannel) => void;
|
|
||||||
stream: (stream: MediaStream) => void;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user