From e1ca8e1c16669c180aaba2a2bb78aeac0eecfddf Mon Sep 17 00:00:00 2001 From: Bas van den Aakster Date: Thu, 13 Nov 2025 00:05:29 +0100 Subject: [PATCH] Fix multiple connect events and add leave method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add hasConnected flag to prevent duplicate connect events - Add leave() method to RondevuConnection to end sessions - Add leave() API method to call /leave endpoint - Version 0.3.5 The connect event will now only fire once per connection, fixing the issue where it could fire multiple times as the WebRTC connectionState transitions. The leave() method allows either peer to end the session by deleting the offer from the server. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- package.json | 2 +- src/client.ts | 19 +++++++++++++++++++ src/connection.ts | 24 +++++++++++++++++++++--- src/rondevu.ts | 2 +- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2073e16..90a0871 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xtr-dev/rondevu-client", - "version": "0.3.4", + "version": "0.3.5", "description": "TypeScript client for Rondevu peer signaling and discovery server", "type": "module", "main": "dist/index.js", diff --git a/src/client.ts b/src/client.ts index 27b50a1..7ab4efc 100644 --- a/src/client.ts +++ b/src/client.ts @@ -186,4 +186,23 @@ export class RondevuAPI { 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 }), + }); + } } diff --git a/src/connection.ts b/src/connection.ts index 2afe836..32f431c 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -20,6 +20,7 @@ export class RondevuConnection extends EventEmitter { private connectionTimer?: ReturnType; private isPolling: boolean = false; private isClosed: boolean = false; + private hasConnected: boolean = false; private wrtc?: WebRTCPolyfill; private RTCIceCandidate: typeof RTCIceCandidate; @@ -94,9 +95,12 @@ export class RondevuConnection extends EventEmitter { switch (state) { case 'connected': - this.clearConnectionTimeout(); - this.stopPolling(); - this.emit('connect'); + if (!this.hasConnected) { + this.hasConnected = true; + this.clearConnectionTimeout(); + this.stopPolling(); + this.emit('connect'); + } break; case 'disconnected': @@ -283,6 +287,20 @@ export class RondevuConnection extends EventEmitter { } } + /** + * Leave the session by deleting the offer on the server and closing the connection + * This ends the session for all connected peers + */ + async leave(): Promise { + try { + await this.client.leave(this.id); + } catch (err) { + // Ignore errors - session might already be expired + console.debug('Leave error (ignored):', err); + } + this.close(); + } + /** * Close the connection and cleanup resources */ diff --git a/src/rondevu.ts b/src/rondevu.ts index 80eb9c7..63bc43c 100644 --- a/src/rondevu.ts +++ b/src/rondevu.ts @@ -62,7 +62,7 @@ export class Rondevu { private async checkServerVersion(): Promise { try { const { version: serverVersion } = await this.api.health(); - const clientVersion = '0.3.4'; // Should match package.json + const clientVersion = '0.3.5'; // Should match package.json if (!this.isVersionCompatible(clientVersion, serverVersion)) { console.warn(