webrtc-phoenix-client
v1.0.0
Published
Browser-only WebRTC peer client for Phoenix Channels (signaling + ordered data messaging)
Downloads
28
Readme
webrtc-phoenix-client
Browser-only WebRTC peer client that uses Phoenix Channels for signaling, and a reliable ordered RTCDataChannel for messaging.
Install
npm i webrtc-phoenix-clientNotes
- Browser-only: Node is not supported (this library expects browser WebRTC globals like
RTCPeerConnection). - For real-world NAT traversal, you will likely need STUN/TURN via
rtcConfig.iceServers. - Send semantics:
sendMessage()resolves when the message is queued/sent on the localRTCDataChannel(it does not wait for a remote application-level ACK).
Usage
import { Peers } from "webrtc-phoenix-client";
// 1) Create peers instance
const peers = new Peers({
url: "wss://your-host.com/webrtc_socket",
// rtcConfig: { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] },
});
// 2) Create/store identity (publicId + privateId)
const myId = await peers.generateID();
// persist myId.privateId somewhere safe if you want stable identity across reloads
// 3) Init: connects to Phoenix + registers ID
const initRes = await peers.init(myId);
if (initRes !== "ok") throw new Error(`init failed: ${initRes}`);
console.log("My public ID:", myId.publicId);
// 4) Optional: gate inbound connections
peers.onPeerRequest(async (fromId) => {
// return true to accept, false to reject
return confirm(`Accept connection from ${fromId}?`);
});
// 5) Peer lifecycle hooks
peers.onPeerConnected((peer) => {
console.log("connected:", peer.id, peer.pc, peer.dc);
});
peers.onPeerDisconnected((peerId) => {
console.log("disconnected:", peerId);
});
// 6) Messaging
peers.onMessage((from, msg) => {
console.log("message from", from, msg);
});
// Start connecting (idempotent per peer; concurrent calls share the same attempt)
const conn = await peers.addPeer("peerPublicIdHere");
if (conn.status !== "connected") {
console.warn("connect aborted:", conn.reason, conn.error);
} else {
// Send a JS object. Nested Blobs / Files / ArrayBuffers / TypedArrays are supported.
const sendRes = await peers.sendMessage(conn.peer.id, {
hello: "world",
file: (document.querySelector("#file") as HTMLInputElement).files?.[0],
});
console.log("send result:", sendRes);
}API (high level)
Identity
peers.generateID() -> Promise<{ publicId, privateId }>peers.init({ publicId, privateId }) -> Promise<"ok" | "in-use" | "auth failed">
Peering
peers.addPeer(peerPublicId) -> Promise<{ status: "connected", peer } | { status: "aborted", reason, error? }>peers.onPeerRequest((peerId) => boolean | Promise<boolean>)— default accepts allpeers.onPeerConnected((peer) => void)peers.onPeerDisconnected((peerId) => void)peers.removePeer(peerId)— closes and removes the peer
Messaging
peers.sendMessage(to, obj) -> Promise<SendMessageResult>(strict: does not auto-connect)peers.broadcast(obj) -> Promise<Record<peerId, SendMessageResult>>peers.onMessage((from, obj) => void)— receives the reconstructed JS object
Underlying WebRTC
addPeer()resolves withpeer.pc: RTCPeerConnectionandpeer.dc: RTCDataChannel- Renegotiation is supported via the Perfect Negotiation pattern.
