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(