mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 10:53:24 +00:00
Compare commits
2 Commits
6c2fd7952e
...
v0.9.1
| Author | SHA1 | Date | |
|---|---|---|---|
| a550641993 | |||
| 04603cfe2d |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/rondevu-client",
|
"name": "@xtr-dev/rondevu-client",
|
||||||
"version": "0.7.12",
|
"version": "0.9.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@xtr-dev/rondevu-client",
|
"name": "@xtr-dev/rondevu-client",
|
||||||
"version": "0.7.12",
|
"version": "0.9.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/ed25519": "^3.0.0",
|
"@noble/ed25519": "^3.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@xtr-dev/rondevu-client",
|
"name": "@xtr-dev/rondevu-client",
|
||||||
"version": "0.9.0",
|
"version": "0.9.1",
|
||||||
"description": "TypeScript client for Rondevu with durable WebRTC connections, automatic reconnection, and message queuing",
|
"description": "TypeScript client for Rondevu with durable WebRTC connections, automatic reconnection, and message queuing",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
@@ -40,13 +40,22 @@ export class ExchangingIceState extends PeerState {
|
|||||||
this.lastIceTimestamp
|
this.lastIceTimestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (candidates.length > 0) {
|
||||||
|
console.log(`📥 Received ${candidates.length} remote ICE candidate(s)`);
|
||||||
|
}
|
||||||
|
|
||||||
for (const cand of candidates) {
|
for (const cand of candidates) {
|
||||||
if (cand.candidate && cand.candidate.candidate && cand.candidate.candidate !== '') {
|
if (cand.candidate && cand.candidate.candidate && cand.candidate.candidate !== '') {
|
||||||
|
const type = cand.candidate.candidate.includes('typ host') ? 'host' :
|
||||||
|
cand.candidate.candidate.includes('typ srflx') ? 'srflx' :
|
||||||
|
cand.candidate.candidate.includes('typ relay') ? 'relay' : 'unknown';
|
||||||
|
console.log(`🧊 Adding remote ${type} ICE candidate:`, cand.candidate.candidate);
|
||||||
try {
|
try {
|
||||||
await this.peer.pc.addIceCandidate(new this.peer.RTCIceCandidate(cand.candidate));
|
await this.peer.pc.addIceCandidate(new this.peer.RTCIceCandidate(cand.candidate));
|
||||||
|
console.log(`✅ Added remote ${type} ICE candidate`);
|
||||||
this.lastIceTimestamp = cand.createdAt;
|
this.lastIceTimestamp = cand.createdAt;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Failed to add ICE candidate:', err);
|
console.warn(`⚠️ Failed to add remote ${type} ICE candidate:`, err);
|
||||||
this.lastIceTimestamp = cand.createdAt;
|
this.lastIceTimestamp = cand.createdAt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -54,7 +63,7 @@ export class ExchangingIceState extends PeerState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error polling for ICE candidates:', err);
|
console.error('❌ Error polling for ICE candidates:', err);
|
||||||
if (err instanceof Error && err.message.includes('not found')) {
|
if (err instanceof Error && err.message.includes('not found')) {
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
const { FailedState } = await import('./failed-state.js');
|
const { FailedState } = await import('./failed-state.js');
|
||||||
|
|||||||
@@ -105,18 +105,23 @@ export default class RondevuPeer extends EventEmitter<PeerEvents> {
|
|||||||
*/
|
*/
|
||||||
private setupPeerConnection(): void {
|
private setupPeerConnection(): void {
|
||||||
this.connectionStateChangeHandler = () => {
|
this.connectionStateChangeHandler = () => {
|
||||||
|
console.log(`🔌 Connection state changed: ${this.pc.connectionState}`);
|
||||||
switch (this.pc.connectionState) {
|
switch (this.pc.connectionState) {
|
||||||
case 'connected':
|
case 'connected':
|
||||||
|
console.log('✅ WebRTC connection established');
|
||||||
this.setState(new ConnectedState(this));
|
this.setState(new ConnectedState(this));
|
||||||
this.emitEvent('connected');
|
this.emitEvent('connected');
|
||||||
break;
|
break;
|
||||||
case 'disconnected':
|
case 'disconnected':
|
||||||
|
console.log('⚠️ WebRTC connection disconnected');
|
||||||
this.emitEvent('disconnected');
|
this.emitEvent('disconnected');
|
||||||
break;
|
break;
|
||||||
case 'failed':
|
case 'failed':
|
||||||
|
console.log('❌ WebRTC connection failed');
|
||||||
this.setState(new FailedState(this, new Error('Connection failed')));
|
this.setState(new FailedState(this, new Error('Connection failed')));
|
||||||
break;
|
break;
|
||||||
case 'closed':
|
case 'closed':
|
||||||
|
console.log('🔒 WebRTC connection closed');
|
||||||
this.setState(new ClosedState(this));
|
this.setState(new ClosedState(this));
|
||||||
this.emitEvent('disconnected');
|
this.emitEvent('disconnected');
|
||||||
break;
|
break;
|
||||||
@@ -124,6 +129,18 @@ export default class RondevuPeer extends EventEmitter<PeerEvents> {
|
|||||||
};
|
};
|
||||||
this.pc.addEventListener('connectionstatechange', this.connectionStateChangeHandler);
|
this.pc.addEventListener('connectionstatechange', this.connectionStateChangeHandler);
|
||||||
|
|
||||||
|
// Add ICE connection state logging
|
||||||
|
const iceConnectionStateHandler = () => {
|
||||||
|
console.log(`🧊 ICE connection state: ${this.pc.iceConnectionState}`);
|
||||||
|
};
|
||||||
|
this.pc.addEventListener('iceconnectionstatechange', iceConnectionStateHandler);
|
||||||
|
|
||||||
|
// Add ICE gathering state logging
|
||||||
|
const iceGatheringStateHandler = () => {
|
||||||
|
console.log(`🔍 ICE gathering state: ${this.pc.iceGatheringState}`);
|
||||||
|
};
|
||||||
|
this.pc.addEventListener('icegatheringstatechange', iceGatheringStateHandler);
|
||||||
|
|
||||||
this.dataChannelHandler = (event: RTCDataChannelEvent) => {
|
this.dataChannelHandler = (event: RTCDataChannelEvent) => {
|
||||||
this.emitEvent('datachannel', event.channel);
|
this.emitEvent('datachannel', event.channel);
|
||||||
};
|
};
|
||||||
@@ -135,7 +152,13 @@ export default class RondevuPeer extends EventEmitter<PeerEvents> {
|
|||||||
this.pc.addEventListener('track', this.trackHandler);
|
this.pc.addEventListener('track', this.trackHandler);
|
||||||
|
|
||||||
this.iceCandidateErrorHandler = (event: Event) => {
|
this.iceCandidateErrorHandler = (event: Event) => {
|
||||||
console.error('ICE candidate error:', event);
|
const iceError = event as RTCPeerConnectionIceErrorEvent;
|
||||||
|
console.error(`❌ ICE candidate error: ${iceError.errorText || 'Unknown error'}`, {
|
||||||
|
errorCode: iceError.errorCode,
|
||||||
|
url: iceError.url,
|
||||||
|
address: iceError.address,
|
||||||
|
port: iceError.port
|
||||||
|
});
|
||||||
};
|
};
|
||||||
this.pc.addEventListener('icecandidateerror', this.iceCandidateErrorHandler);
|
this.pc.addEventListener('icecandidateerror', this.iceCandidateErrorHandler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,19 @@ export abstract class PeerState {
|
|||||||
if (event.candidate && this.peer.offerId) {
|
if (event.candidate && this.peer.offerId) {
|
||||||
const candidateData = event.candidate.toJSON();
|
const candidateData = event.candidate.toJSON();
|
||||||
if (candidateData.candidate && candidateData.candidate !== '') {
|
if (candidateData.candidate && candidateData.candidate !== '') {
|
||||||
|
const type = candidateData.candidate.includes('typ host') ? 'host' :
|
||||||
|
candidateData.candidate.includes('typ srflx') ? 'srflx' :
|
||||||
|
candidateData.candidate.includes('typ relay') ? 'relay' : 'unknown';
|
||||||
|
console.log(`🧊 Generated ${type} ICE candidate:`, candidateData.candidate);
|
||||||
try {
|
try {
|
||||||
await this.peer.offersApi.addIceCandidates(this.peer.offerId, [candidateData]);
|
await this.peer.offersApi.addIceCandidates(this.peer.offerId, [candidateData]);
|
||||||
|
console.log(`✅ Sent ${type} ICE candidate to server`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error sending ICE candidate:', err);
|
console.error(`❌ Error sending ${type} ICE candidate:`, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!event.candidate) {
|
||||||
|
console.log('🧊 ICE gathering complete (null candidate)');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.peer.pc.addEventListener('icecandidate', this.iceCandidateHandler);
|
this.peer.pc.addEventListener('icecandidate', this.iceCandidateHandler);
|
||||||
|
|||||||
Reference in New Issue
Block a user