npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

peerpyrtc-client

v0.5.3

Published

Python-backed WebRTC helper library for JS clients

Readme

peerpyrtc-client

Socket.io-compatible WebRTC client for building serverless, real-time peer-to-peer applications.

This package provides a Socket.io-like JavaScript client that replaces WebSockets with true peer-to-peer WebRTC DataChannels. Build chat apps, games, collaborative tools, and real-time dashboards without persistent server connections.

🚀 Key Features

  • 🔄 Socket.io Compatible: Drop-in replacement with emit(), broadcast(), and event-driven architecture
  • ⚡ Multi-Room Support: WebRTCRoomManager for handling multiple rooms simultaneously
  • 🎯 Real-time Peer Management: Automatic join/leave detection, host election, room state sync
  • 🛡️ Production Ready: Built-in TURN servers, reconnection, error handling, and failover
  • 📡 Event-Driven: Comprehensive callback system for peer events and room management
  • 🎮 Multi-Purpose: Perfect for chat, gaming, collaboration, IoT, trading, video conferencing

📦 Installation

npm install peerpyrtc-client

CDN Usage

<script src="https://unpkg.com/peerpyrtc-client/dist/peerpyrtc.umd.js"></script>
<script>
  const { WebRTCConnection } = window.WebRTCConnection;
  const rtc = new WebRTCConnection("my-room");
  rtc.onOpen = () => rtc.sendMessage("Hello World!");
  rtc.connect();
</script>

🚀 Quick Start

Basic Usage (Single Room)

import { WebRTCConnection } from 'peerpyrtc-client';

const rtc = new WebRTCConnection("game-room", { debug: true });

// Socket.io-like event handling
rtc.onMessage = (senderId, message, event) => {
  if (event === 'player-move') {
    console.log(`Player ${senderId} moved:`, message);
  } else {
    console.log(`Chat from ${senderId}:`, message);
  }
};

rtc.onOpen = () => {
  console.log("Connected! Peers:", rtc.getPeerCount());
  
  // Send regular message
  rtc.sendMessage("Hello everyone!");
  
  // Emit custom events
  rtc.emit('player-move', { x: 5, y: 3 });
  
  // Broadcast to all peers
  rtc.broadcast('game-start', { level: 1 });
};

// Real-time peer management
rtc.onPeerJoined = (peer) => {
  console.log(`🟢 ${peer.id} joined! Host: ${peer.isHost}`);
};

rtc.onPeerLeft = (peer) => {
  console.log(`🔴 ${peer.id} left the room`);
};

// Connect to room
await rtc.connect();

Multi-Room Management

import { WebRTCRoomManager } from 'peerpyrtc-client';

const manager = new WebRTCRoomManager("user123", { debug: true });

// Global event handlers (apply to all rooms)
manager.on('chat-message', (roomId, senderId, message) => {
  console.log(`Message in ${roomId} from ${senderId}:`, message);
});

manager.on('user-active', (roomId, senderId, message) => {
  console.log(`User ${senderId} active in ${roomId}`);
});

// Room-specific handlers
manager.onRoom('lobby', 'player-joined', (roomId, senderId, data) => {
  console.log(`Player joined lobby:`, data);
});

// Join multiple rooms
await manager.joinRooms(['lobby', 'game-1', 'chat-general']);

// Join multiple rooms
await manager.joinRooms(['lobby', 'game-1', 'chat-general']);

// Emit to specific room
manager.emit('lobby', 'player-joined', { playerId: 'user123' });

// Send message to specific room
manager.sendMessage('game-1', 'Hello game room!');

📚 API Reference

WebRTCConnection

Constructor

const rtc = new WebRTCConnection(roomName, options)
  • roomName: String - Room identifier
  • options: Object (optional)
    • peerId: String - Custom peer ID (auto-generated if not provided)
    • debug: Boolean - Enable debug logging (default: false)
    • maxReconnectAttempts: Number - Max reconnection attempts (default: 3)
    • reconnectDelay: Number - Delay between reconnections in ms (default: 2000)

Core Methods

// Connection
await rtc.connect()                    // Connect to room
await rtc.closeConnection()            // Leave room
rtc.isConnected()                      // Check connection status

// Messaging (Socket.io style)
rtc.sendMessage(message)               // Send chat message
rtc.emit(event, data)                  // Emit custom event
rtc.broadcast(event, data)             // Broadcast to all peers

// Room Management
rtc.getRoomPeers()                     // Get all peers in room
rtc.getPeerCount()                     // Get number of peers
rtc.isRoomHost()                       // Check if you're the host

Event Callbacks

// Core Events
rtc.onOpen = () => {}                  // Connection established
rtc.onClose = () => {}                 // Connection closed
rtc.onError = (error) => {}            // Connection error
rtc.onMessage = (senderId, message, event) => {} // Receive message/event

// Peer Management Events
rtc.onPeerJoined = (peer) => {}        // New peer joins
rtc.onPeerLeft = (peer) => {}          // Peer leaves
rtc.onRoomUpdate = (peers) => {}       // Room state changes
rtc.onStatusChange = (status) => {}    // Connection status updates

WebRTCRoomManager

Constructor

const manager = new WebRTCRoomManager(userId, options)
  • userId: String - Unique user identifier
  • options: Object (optional)
    • debug: Boolean - Enable debug logging

Multi-Room Methods

// Room Management
await manager.joinRoom(roomId, options)        // Join single room
await manager.joinRooms([roomIds])             // Join multiple rooms
await manager.leaveRoom(roomId)                // Leave room
await manager.leaveAllRooms()                  // Leave all rooms

// Smart Messaging
manager.emit(roomId, event, data)              // Emit to specific room
manager.emit(roomId, event, data)              // Emit to specific room
manager.sendMessage(roomId, message)           // Send message to room
manager.sendMessage(roomId, message)           // Send message to room

// Event Handling
manager.on(event, handler)                     // Global event handler
manager.onRoom(roomId, event, handler)         // Room-specific handler

// Status & Info
manager.getStatus()                            // Get all room statuses
manager.getRoom(roomId)                        // Get specific room connection
manager.getRoomIds()                           // Get all joined room IDs
manager.isConnectedTo(roomId)                  // Check room connection

🎯 Real-World Examples

Chat Application with Seen Status

const rtc = new WebRTCConnection(`chat-${roomId}`);

rtc.onMessage = (senderId, message, event) => {
  if (event === 'user-typing') {
    showTypingIndicator(senderId);
  } else if (event === 'user-active') {
    markMessagesAsSeen(senderId, message.activeTime);
  } else if (event === 'user-joined') {
    showUserJoined(senderId, message.userName);
  } else {
    displayMessage(senderId, message.text);
  }
};

// Send typing indicator
rtc.emit('user-typing', { typing: true });

// Mark messages as seen when user opens chat
rtc.emit('user-active', { 
  activeTime: Date.now(),
  userId: currentUser.id 
});

// Notify when user joins
rtc.emit('user-joined', {
  userId: currentUser.id,
  userName: currentUser.name,
  joinTime: Date.now()
});

Multiplayer Game

const game = new WebRTCConnection(`game-${gameId}`);

game.onMessage = (playerId, data, event) => {
  switch(event) {
    case 'player-move':
      updatePlayerPosition(playerId, data.position);
      break;
    case 'player-attack':
      processAttack(playerId, data.target, data.damage);
      break;
    case 'game-state':
      syncGameState(data);
      break;
  }
};

// Send player actions
game.emit('player-move', { position: { x: 100, y: 200 } });
game.emit('player-attack', { target: 'enemy1', damage: 50 });

// Broadcast game events (if you're the host)
if (game.isRoomHost()) {
  game.broadcast('game-state', getCurrentGameState());
}

Multi-Room Chat Manager

const chatManager = new WebRTCRoomManager(userId);

// Handle messages from all rooms
chatManager.on('chat-message', (roomId, senderId, message) => {
  displayMessage(roomId, senderId, message.text);
  updateChatList(roomId, message.text, senderId);
});

// Handle seen status updates
chatManager.on('user-active', (roomId, senderId, message) => {
  markMessagesAsSeen(roomId, senderId, message.activeTime);
});

// Join multiple chat rooms
await chatManager.joinRooms(['general', 'random', 'tech-talk']);

// Send message to specific room
chatManager.emit('general', 'chat-message', { 
  text: 'Hello everyone!',
  timestamp: Date.now()
});

🔧 Common Issues & Solutions

"Cannot send EVENT - data channel not ready"

Problem: Trying to emit events immediately after connection.

Solution: Wait for connection to be fully established:

rtc.onOpen = () => {
  // Connection is ready, safe to emit
  rtc.emit('user-joined', { userId: 'user123' });
};

// Or use setTimeout for delayed emit
const connection = await rtc.connect();
setTimeout(() => {
  if (rtc.isConnected()) {
    rtc.emit('welcome', { message: 'Hello!' });
  }
}, 1000);

Connection Drops/Reconnection

Problem: Network issues causing disconnections.

Solution: Handle reconnection gracefully:

rtc.onError = (error) => {
  console.log('Connection error:', error);
  // Will auto-reconnect based on maxReconnectAttempts
};

rtc.onClose = () => {
  console.log('Connection closed');
  // Show offline indicator
};

rtc.onOpen = () => {
  console.log('Connected/Reconnected');
  // Re-sync state, show online indicator
};

Multiple Room Management

Problem: Managing connections to multiple rooms manually.

Solution: Use WebRTCRoomManager:

// Instead of managing multiple WebRTCConnection instances
const manager = new WebRTCRoomManager('user123');

// Simple room switching
await manager.joinRoom('room1');
await manager.joinRoom('room2');

// Automatic connection management
manager.emit('room1', 'message', { text: 'Hello room 1' });
manager.emit('room2', 'message', { text: 'Hello room 2' });

🚀 Production Tips

Error Handling

try {
  await rtc.connect();
} catch (error) {
  console.error('Failed to connect:', error);
  showError('Unable to connect to chat. Please try again.');
}

Performance Optimization

// Disable debug in production
const rtc = new WebRTCConnection('room', { 
  debug: process.env.NODE_ENV === 'development' 
});

// Batch multiple events
rtc.emit('batch-update', { 
  events: [
    { type: 'player-move', data: { x: 1, y: 2 } },
    { type: 'player-health', data: { health: 90 } }
  ]
});

Security Best Practices

// Validate incoming data
rtc.onMessage = (senderId, message, event) => {
  // Validate sender
  if (!isValidUser(senderId)) {
    console.warn('Invalid sender:', senderId);
    return;
  }
  
  // Validate message structure
  if (event === 'player-move' && !isValidPosition(message.position)) {
    console.warn('Invalid position data');
    return;
  }
  
  // Process valid message
  handleMessage(senderId, message, event);
};

📝 Version History

  • v0.5.1 - Fixed WebRTCRoomManager event handling
  • v0.5.0 - Added WebRTCRoomManager for multi-room support
  • v0.4.0 - Enhanced connection stability and error handling
  • v0.3.0 - Added peer management and host election
  • v0.2.0 - Socket.io-compatible API
  • v0.1.0 - Initial release

🎆 Why Choose PeerPyRTC?

vs WebSockets

  • No server scaling issues - P2P scales infinitely
  • Lower latency - Direct peer connections
  • Reduced server costs - No persistent connections
  • Better performance - No server bottleneck

vs Socket.io

  • Same familiar API - Drop-in replacement
  • Serverless architecture - True P2P after signaling
  • Built-in peer management - Automatic join/leave detection
  • Production ready - TURN servers, reconnection, failover

Perfect for: Chat apps, games, collaboration tools, IoT dashboards, trading platforms, video conferencing, and any real-time application.

📄 License

MIT License - see LICENSE file for details.


Built with ❤️ for developers who want WebSocket performance without WebSocket complexity.