### Install Trystero and WebRTC Polyfill Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Install the necessary packages for server-side Trystero usage with a WebRTC polyfill. ```bash npm install trystero werift ``` -------------------------------- ### Firebase Pre-initialized App Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Example of joining a room with a pre-initialized Firebase app. This avoids re-initialization and allows for more control over Firebase setup. ```javascript import {initializeApp} from 'firebase/app' import {joinRoom} from '@trystero-p2p/firebase' const firebaseApp = initializeApp({ databaseURL: 'https://myproject.firebaseio.com', // ... other config }) const room = joinRoom({ appId: 'https://myproject.firebaseio.com', relayConfig: { firebaseApp } }, 'room-id') ``` -------------------------------- ### Install Trystero with npm Source: https://github.com/dmotz/trystero/blob/main/README.md Install the Trystero library using npm. This is the recommended way to add Trystero to your project. ```sh npm i trystero ``` -------------------------------- ### Install WebSocket Relay Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Install the WebSocket relay server package using npm. ```bash npm install @trystero-p2p/ws-relay ``` -------------------------------- ### Importing Trystero Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md Examples of how to import the joinRoom function from Trystero, showing both the default Nostr strategy and the MQTT strategy. ```javascript import {joinRoom} from 'trystero' // Default (Nostr) ``` ```javascript import {joinRoom} from '@trystero-p2p/mqtt' // MQTT strategy ``` -------------------------------- ### Configuration Option Documentation Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md Illustrates the format for documenting configuration options, including their properties, types, and descriptions. Use this for documenting any configurable setting. ```markdown ### Option Name | Property | Type | Required | Default | Description | | --- | --- | --- | --- | --- | **Example:** ```javascript const config = {...} ``` ``` -------------------------------- ### Initialize Firebase and Join Room Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Example demonstrating how to initialize the Firebase app and then use it to join a Trystero room. Ensure your databaseURL is correctly set. ```javascript import {initializeApp} from 'firebase/app' import {joinRoom} from '@trystero-p2p/firebase' const firebaseApp = initializeApp({ databaseURL: 'https://myapp.firebaseio.com' }) const room = joinRoom({ appId: 'https://myapp.firebaseio.com', relayConfig: { firebaseApp } }, 'room-1') ``` -------------------------------- ### API Function Documentation Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md Demonstrates the standard format for documenting exported functions, including signature, parameters, return values, and examples. Use this for documenting any public function or method. ```markdown ### functionName(param1, [param2]) **Signature:** ```typescript function functionName(param1: Type1, param2?: Type2): ReturnType ``` **Parameters:** | Parameter | Type | Required | Default | Description | ... **Returns:** Description of return value **Example:** ```javascript // Complete working example ``` **Throws:** When errors occur ``` -------------------------------- ### API Function Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md A complete, working example illustrating the usage of an API function. This should be included in the function's documentation. ```javascript // Complete working example ``` -------------------------------- ### JoinRoomConfig Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md Example of a JoinRoomConfig object used to configure room joining with Trystero. It includes application ID, password, passive mode, relay configuration, trickle ICE, and TURN server settings. ```typescript const config: JoinRoomConfig = { appId: 'my-app-id', password: 'shared-secret-key', passive: false, relayConfig: { urls: ['wss://relay1.example.com', 'wss://relay2.example.com'], redundancy: 2 }, trickleIce: true, turnConfig: [ { urls: ['turn:turn.example.com:3478'], username: 'user', credential: 'pass' } ] } ``` -------------------------------- ### Create a WebSocket Relay Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Set up and start a custom WebSocket relay server for Trystero peers. Ensure the server is listening on the specified port. ```javascript // server.ts / server.js import {createWsRelayServer} from '@trystero-p2p/ws-relay/server' const server = createWsRelayServer({ port: 8080 }) server.ready.then(() => { const addr = server.address() console.log(`Relay listening on ${addr.address}:${addr.port}`) }) ``` -------------------------------- ### Join Room with IPFS Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Example of joining a room using the IPFS strategy with an application ID. ```javascript import {joinRoom} from '@trystero-p2p/ipfs' const room = joinRoom({ appId: 'ipfs-app-v1' }, 'room-1') room.onPeerJoin = peerId => console.log(`${peerId} joined via IPFS`) ``` -------------------------------- ### Minimal Handshake Example Source: https://github.com/dmotz/trystero/blob/main/README.md Demonstrates a basic handshake process between peers to verify identity before establishing a full connection. This example shows how to use `send` and `receive` within the `onPeerHandshake` callback. ```javascript import {joinRoom} from 'trystero' const room = joinRoom({appId: 'my-app'}, 'secure-room', { onPeerHandshake: async (_, send, receive, isInitiator) => { if (isInitiator) { await send({challenge: 'prove-you-know-the-secret'}) const {data} = await receive() if (data?.response !== 'shared-secret') { throw new Error('handshake rejected') } } else { const {data} = await receive() if (data?.challenge !== 'prove-you-know-the-secret') { throw new Error('handshake rejected') } await send({response: 'shared-secret'}) } } }) ``` -------------------------------- ### Type Usage Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md An example demonstrating how to use a defined type. This is included in the type's documentation. ```typescript const example: TypeName = {...} ``` -------------------------------- ### Async/Await Usage Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md Demonstrates the use of async/await for Trystero's Promise-based APIs, common in asynchronous operations. ```javascript const result = await action.request(data, {target: peerId}) ``` -------------------------------- ### Configuration Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md A JavaScript object literal representing a configuration. This is used in the configuration documentation. ```javascript const config = {...} ``` -------------------------------- ### Join Room with MQTT Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Example of joining a room using the MQTT strategy, specifying custom broker URLs. This is suitable for IoT-style deployments. ```javascript import {joinRoom} from '@trystero-p2p/mqtt' const room = joinRoom({ appId: 'iot-app', relayConfig: { urls: ['wss://broker.hivemq.com:8884/mqtt'] } }, 'sensor-network') ``` -------------------------------- ### Start Self-Hosted WebSocket Relay Server Source: https://github.com/dmotz/trystero/blob/main/README.md Use this to start a self-hosted WebSocket relay server on Node or Bun. Ensure the port is accessible. ```javascript import {createWsRelayServer} from '@trystero-p2p/ws-relay/server' createWsRelayServer({port: 8080}) ``` -------------------------------- ### Example PeerHandshake Implementation Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md An example demonstrating how to implement the onPeerHandshake callback for custom peer authentication. This snippet shows a challenge-response mechanism to validate peers. ```typescript const callbacks: JoinRoomCallbacks = { onPeerHandshake: async (peerId, send, receive, isInitiator) => { if (isInitiator) { await send({challenge: 'secret-code'}) const {data} = await receive() if (data?.response !== 'valid-response') { throw new Error('handshake failed') } } else { const {data} = await receive() if (data?.challenge !== 'secret-code') { throw new Error('invalid challenge') } await send({response: 'valid-response'}) } }, handshakeTimeoutMs: 5000 } ``` -------------------------------- ### Join Room with Supabase Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Example of joining a room using the Supabase strategy with project URL and API key. ```javascript import {joinRoom} from '@trystero-p2p/supabase' const room = joinRoom({ appId: 'https://xyzabc.supabase.co', relayConfig: { supabaseKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' } }, 'collaboration-room') ``` -------------------------------- ### TurnServerConfig Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md Example of a TurnServerConfig object for configuring a TURN server for WebRTC NAT traversal. It specifies the server URL, username, and credential. ```typescript const turnConfig: TurnServerConfig = { urls: 'turn:turn.example.com:3478', username: 'alice', credential: 'secret123' } ``` -------------------------------- ### TypeScript Type Annotation Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md Illustrates how TypeScript type annotations are used in examples, which are also compatible with JavaScript. ```typescript const config: JoinRoomConfig = {appId: 'my-app'} ``` -------------------------------- ### Type Documentation Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md Shows the standard format for documenting exported types or interfaces, including their definition, properties, and usage. Use this for documenting any public type. ```markdown ### TypeName **Type Definition:** ```typescript type TypeName = {...} ``` **Properties:** | Property | Type | Required | Description | ... **Used By:** Functions that accept/return this type **Example:** ```typescript const example: TypeName = {...} ``` ``` -------------------------------- ### Nostr Custom Relay Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Example of joining a room with custom Nostr relay URLs. Ensure your provided URLs are valid Nostr relays. ```javascript import {joinRoom} from 'trystero' const room = joinRoom({ appId: 'decentralized-app', relayConfig: { urls: [ 'wss://my-relay1.example.com', 'wss://my-relay2.example.com' ] } }, 'room-123') ``` -------------------------------- ### Archive Node Setup with Trystero Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Set up an archive node using Trystero on a server. This node passively listens for messages and stores them. Requires a WebRTC polyfill. ```javascript import {joinRoom} from 'trystero' import {RTCPeerConnection} from 'werift' const room = joinRoom({ appId: 'my-app', rtcPolyfill: RTCPeerConnection, passive: true // Only listen }, 'archive') const messages = [] const chat = room.makeAction('message') chat.onMessage = (text, {peerId}) => { messages.push({ timestamp: Date.now(), peerId, text }) // Persist to database saveMessage({peerId, text}) } // Serve archived messages app.get('/api/messages', (req, res) => { res.json(messages) }) ``` -------------------------------- ### Simple WebSocket Tracker Implementation Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md An example demonstrating how to create a custom signaling strategy using WebSockets as a tracker. This implementation handles WebSocket connection, message routing, and peer signaling. ```javascript import {createStrategy, toJson, fromJson} from '@trystero-p2p/core' export const joinRoom = createStrategy({ init: config => { return new Promise((resolve, reject) => { const ws = new WebSocket(config.relayConfig.trackerUrl) ws.onopen = () => resolve(ws) ws.onerror = reject }) }, subscribe: (ws, rootTopic, selfTopic, onMessage, getOffers) => { const handler = event => { const msg = fromJson(event.data) const [topic, payload, signalPeer] = [ msg.topic, msg.payload, (peerId, signal) => onMessage(peerId, msg, (signalStr) => { ws.send(toJson({ type: 'signal', topic: peerId, offer: signalStr })) }) ] if (msg.type === 'offer') { onMessage(msg.peerId, msg.offer, signalPeer) } } ws.addEventListener('message', handler) return () => ws.removeEventListener('message', handler) }, announce: async (ws, rootTopic, selfTopic, extraPayload) => { ws.send(toJson({ type: 'announce', topic: rootTopic, peerId: selfId })) } }) ``` -------------------------------- ### Relay Node Setup with Trystero Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Implement a relay node using Trystero on a server. This node echoes all received messages to other connected peers. Requires a WebRTC polyfill. ```javascript import {joinRoom} from 'trystero' import {RTCPeerConnection} from 'werift' const room = joinRoom({ appId: 'relay-network', rtcPolyfill: RTCPeerConnection }, 'relay-1') const broadcast = room.makeAction('broadcast') // Echo all messages to other peers broadcast.onMessage = (data, {peerId}) => { const otherPeers = Object.keys(room.getPeers()).filter(id => id !== peerId) if (otherPeers.length > 0) { broadcast.send(data, {target: otherPeers}) } } ``` -------------------------------- ### Node.js Load Balancer Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Example of a Node.js load balancer using node-http-proxy to distribute WebSocket connections across multiple relay servers. It implements basic round-robin routing. ```javascript // load-balancer.js (e.g., using node-http-proxy) const httpProxy = require('http-proxy') const http = require('http') const relays = [ 'http://relay1:8080', 'http://relay2:8080', 'http://relay3:8080' ] let index = 0 const proxy = httpProxy.createProxyServer({ target: relays[index % relays.length], ws: true }) const server = http.createServer((req, res) => { index++ proxy.web(req, res) }) server.on('upgrade', (req, socket, head) => { index++ proxy.ws(req, socket, head) }) server.listen(80) ``` -------------------------------- ### Create and Monitor Durable WebSocket Relay Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md This JavaScript example demonstrates how to create a durable WebSocket relay server using Trystero, including basic monitoring of active clients and graceful shutdown handling. ```javascript import {createWsRelayServer} from '@trystero-p2p/ws-relay/server' const server = createWsRelayServer({ port: process.env.PORT || 8080, onError: (error) => { console.error('Server error:', error) } }) server.ready.then(() => { const addr = server.address() console.log(`WebSocket relay listening on port ${addr?.port || 8080}`) }) // Monitor server health setInterval(() => { const clients = server.wss.clients.size const topicCount = Object.keys( // Access internal subscription map (if available via ws internals) ).length console.log(`Active clients: ${clients}`) }, 30000) // Graceful shutdown process.on('SIGTERM', async () => { console.log('SIGTERM received, shutting down gracefully...') // Optionally notify clients server.publish('__system__', { type: 'shutdown', message: 'Server shutting down' }) await new Promise(resolve => setTimeout(resolve, 1000)) await server.close() process.exit(0) }) ``` -------------------------------- ### Join a Trystero Room Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Use `joinRoom` to add the local user to a room. Call this with the same `roomId` to get the same room instance. Configure with `appId` and optional settings. Set up `onPeerJoin` and `onPeerLeave` callbacks for event handling. Use `room.leave()` to exit. ```javascript import {joinRoom} from 'trystero' const config = {appId: 'my-unique-app-id'} const room = joinRoom(config, 'chat-room-1') room.onPeerJoin = peerId => console.log(`${peerId} joined`) room.onPeerLeave = peerId => console.log(`${peerId} left`) // Later: leave the room room.leave() ``` -------------------------------- ### Obtain Let's Encrypt Certificate Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Secures a domain with a Let's Encrypt certificate for production use. Requires Certbot to be installed. ```bash # Let's Encrypt (production) certbot certonly --standalone -d relay.example.com ``` -------------------------------- ### High-Redundancy Decentralized Setup Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Set up Trystero for a highly redundant decentralized application by increasing the number of relays and optionally including TURN servers for direct connection fallback. ```javascript const config = { appId: 'resilient-app', relayConfig: { redundancy: 10, // Connect to 10 relays instead of default 5 manualReconnection: false }, turnConfig: [ // Add TURN for peer pairs that can't connect directly { urls: 'turn:turn1.cloudflare.com', username: 'user', credential: 'key' } ] } ``` -------------------------------- ### React Component with Trystero Hooks Source: https://github.com/dmotz/trystero/blob/main/README.md Example React component demonstrating how to use Trystero hooks for real-time peer-to-peer communication, including syncing state and handling peer joins. ```jsx import {joinRoom} from 'trystero' import {useState} from 'react' const trysteroConfig = {appId: 'thurn-und-taxis'} export default function App({roomId}) { const room = joinRoom(trysteroConfig, roomId) const colorAction = room.makeAction('color') const [myColor, setMyColor] = useState('#c0ffee') const [peerColors, setPeerColors] = useState({}) // whenever new peers join the room, send my color to them: room.onPeerJoin = peer => colorAction.send(myColor, {target: peer}) // listen for peers sending their colors and update the state accordingly: colorAction.onMessage = (color, {peerId}) => setPeerColors(peerColors => ({...peerColors, [peerId]: color})) const updateColor = e => { const {value} = e.target // when updating my own color, broadcast it to all peers: colorAction.send(value) setMyColor(value) } return ( <>

Trystero + React

My color:

Peer colors:

) } ``` -------------------------------- ### Handle Handshake Errors with Error Throwing Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md Demonstrates how to implement handshake logic with explicit error throwing to deny peers. This example shows both initiator and non-initiator roles and logs handshake failures. ```javascript const room = joinRoom({appId: 'my-app'}, 'secure-room', { onPeerHandshake: async (peerId, send, receive, isInitiator) => { try { if (isInitiator) { await send({challenge: 'verify-yourself'}) const {data, metadata} = await receive() if (data?.response !== 'correct-answer') { throw new Error('invalid response from peer') } } else { const {data} = await receive() if (data?.challenge !== 'verify-yourself') { throw new Error('invalid challenge') } await send({response: 'correct-answer'}) } } catch (err) { console.error(`Handshake with ${peerId} failed:`, err) throw err // Deny the peer } }, handshakeTimeoutMs: 3000 }) ``` -------------------------------- ### Implement Custom WebSocket Pub/Sub Strategy Source: https://github.com/dmotz/trystero/blob/main/README.md Create a custom signaling strategy for Trystero using `createTopicStrategy`. This example demonstrates a simple WebSocket pub/sub relay. Ensure your WebSocket server handles the specified message format. ```javascript import {createTopicStrategy, toJson} from '@trystero-p2p/core' export const joinRoom = createTopicStrategy({ // Define init as a function that returns a promise of your signaling client. // Resolve the promise when your client is ready to send messages. // You can also return an array of client promises for redundancy. // In this case, the client is a single WebSocket. init: config => new Promise((resolve, reject) => { const ws = new WebSocket(config.relayConfig.urls[0]) ws.addEventListener('open', () => resolve(ws), {once: true}) ws.addEventListener('error', reject, {once: true}) }), // Subscribe to one topic. Trystero decides which topics are needed and when. subscribeTopic: (client, topic, onMessage) => { const onWsMessage = event => { const message = JSON.parse(String(event.data)) if (message.topic !== topic) { return } onMessage(message.topic, message.payload) } client.addEventListener('message', onWsMessage) client.send(toJson({type: 'subscribe', topic})) return () => { client.send(toJson({type: 'unsubscribe', topic})) client.removeEventListener('message', onWsMessage) } }, // Publish a payload to one topic. publishTopic: (client, topic, payload) => client.send( toJson({ type: 'publish', topic, payload }) ) }) const room = joinRoom( {appId: 'my-app-id', relayConfig: {urls: ['wss://my-relay.example']}}, 'my-room-id' ) ``` -------------------------------- ### Import Trystero Functions Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Imports necessary functions from the Trystero library for room management and peer identification. This is a common setup for using Trystero. ```javascript import {joinRoom, selfId, getRelaySockets, pauseRelayReconnection, resumeRelayReconnection} from 'trystero' ``` -------------------------------- ### Join Room with BitTorrent Strategy (Passive Mode) Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Example of joining a room using the BitTorrent strategy in passive (listen-only) mode. This reduces tracker load for backup nodes. ```javascript import {joinRoom} from '@trystero-p2p/torrent' const room = joinRoom({ appId: 'my-app', passive: true // Listen-only node }, 'backup-node') ``` -------------------------------- ### Docker Deployment for HTTP Relay Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Dockerfile for deploying the Trystero relay server for standard HTTP WebSocket connections. Installs dependencies and copies server files. ```dockerfile FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY server.js . EXPOSE 8080 CMD ["node", "server.js"] ``` -------------------------------- ### Send Data with Progress and Metadata Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Utilize the `send` method of a Trystero action object to transmit data to peers. You can specify target peers, include metadata, and monitor transfer progress with a callback. This example demonstrates sending a blob with a filename in metadata and logging progress. ```javascript const file = room.makeAction('file') file.send(blob, { target: peerId, metadata: {filename: 'document.pdf'}, onProgress: (percent, {peerId}) => { console.log(`${percent * 100}% sent to ${peerId}`) } }) ``` -------------------------------- ### Running Trystero Server-Side with WebRTC Polyfill Source: https://github.com/dmotz/trystero/blob/main/README.md Demonstrates how to use Trystero in a Node.js or Bun environment by importing a WebRTC polyfill like 'werift'. This enables server-side peers for state persistence or lightweight clients. ```js import {joinRoom} from 'trystero' import {RTCPeerConnection} from 'werift' const room = joinRoom( {appId: 'your-app-id', rtcPolyfill: RTCPeerConnection}, 'your-room-name' ) ``` -------------------------------- ### Create Audio Chatroom with Trystero Source: https://github.com/dmotz/trystero/blob/main/README.md Set up local audio streams and handle incoming peer audio streams for a chatroom. Ensure `room.addStream` is called for both current and future peers. ```javascript // this object can store audio instances for later const peerAudios = {} // get a local audio stream from the microphone const selfStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }) // send stream to peers currently in the room room.addStream(selfStream) // send stream to peers who join later room.onPeerJoin = peerId => room.addStream(selfStream, {target: peerId}) // handle streams from other peers room.onPeerStream = (stream, peerId) => { // create an audio instance and set the incoming stream const audio = new Audio() audio.srcObject = stream audio.autoplay = true // add the audio to peerAudios object if you want to address it for something // later (volume, etc.) peerAudios[peerId] = audio } ``` -------------------------------- ### Waiting for Server Readiness Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Await the `ready` promise to ensure the server is operational before accepting connections. Handle potential startup failures by catching errors. ```javascript const server = createWsRelayServer({port: 8080}) try { await server.ready console.log('Server started') } catch (error) { console.error('Failed to start:', error) } ``` -------------------------------- ### Firebase Security Rules Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Example of Firebase security rules for Trystero. These rules control read and write access to your Firebase Realtime Database for Trystero rooms. ```json { "rules": { ".read": false, ".write": false, "__trystero__": { ".read": false, ".write": false, "$room_id": { ".read": true, ".write": true } } } } ``` -------------------------------- ### Create Basic WebSocket Relay Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Set up a basic WebSocket relay server listening on a specified port. The server's address is logged upon successful startup. ```javascript import {createWsRelayServer} from '@trystero-p2p/ws-relay/server' const server = createWsRelayServer({ port: 8080 }) server.ready.then(() => { const address = server.address() console.log(`Relay listening on ${address.address}:${address.port}`) }) ``` -------------------------------- ### Join Room with Different Signaling Strategies Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Demonstrates importing the `joinRoom` function from various Trystero signaling strategy packages. Each import allows connection through a different P2P network. ```javascript import {joinRoom} from 'trystero' // Nostr (default) import {joinRoom} from '@trystero-p2p/mqtt' // MQTT import {joinRoom} from '@trystero-p2p/torrent' // BitTorrent import {joinRoom} from '@trystero-p2p/firebase' // Firebase import {joinRoom} from '@trystero-p2p/supabase' // Supabase import {joinRoom} from '@trystero-p2p/ipfs' // IPFS import {joinRoom} from '@trystero-p2p/ws-relay' // WebSocket Relay ``` -------------------------------- ### Getting Subscriber Counts Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Obtain the number of connected clients using `getSubscriberCount()`. Provide a topic name to get the count for a specific topic, or call without arguments for the total count. ```javascript server.ready.then(() => { const total = server.getSubscriberCount() const roomACount = server.getSubscriberCount('room-a') console.log(`Total subscribers: ${total}, Room A: ${roomACount}`) }) ``` -------------------------------- ### Type Definition Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md The TypeScript type definition for a data structure. This is part of the type documentation structure. ```typescript type TypeName = {...} ``` -------------------------------- ### Get Connection Statistics Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Retrieves connection statistics for all peers in the room. Useful for debugging connection issues. ```javascript function getConnectionStats() { const peers = room.getPeers() return Object.entries(peers).map(([peerId, connection]) => ({ peerId, state: connection.connectionState, iceState: connection.iceConnectionState, signalingState: connection.signalingState, iceGatheringState: connection.iceGatheringState })) } console.log(getConnectionStats()) ``` -------------------------------- ### Import joinRoom from CDN Source: https://github.com/dmotz/trystero/blob/main/README.md Import the `joinRoom` function from Trystero using a CDN. This is an alternative for projects that do not use a package manager. ```html ``` -------------------------------- ### Connect to Trystero Relay Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Use `joinRoom` to connect to a Trystero relay server. Configure your application ID and relay server URLs. Listen for peer join events. ```javascript import {joinRoom} from '@trystero-p2p/ws-relay' const room = joinRoom({ appId: 'my-app-v1', relayConfig: { urls: [ 'wss://relay.example.com:8443', // WSS (HTTPS) 'ws://relay-backup.internal:8080' // WS (internal) ] } }, 'collaboration-room') room.onPeerJoin = peerId => { console.log(`${peerId} joined`) } ``` -------------------------------- ### getSubscriberCount(topic?: string) Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Returns the number of subscribers. You can get the total number of subscribers across all topics or the count for a specific topic. ```APIDOC ## getSubscriberCount(topic?: string) ### Description Returns the number of subscribers. If topic is provided, returns count for that topic. Otherwise returns total. ### Method `getSubscriberCount(topic?: string)` ### Parameters - **topic** (string) - Optional - The specific topic for which to retrieve the subscriber count. If omitted, returns the total subscriber count. ### Response - **number**: The number of subscribers for the specified topic, or the total number of subscribers if no topic is provided. ### Request Example ```javascript server.ready.then(() => { const total = server.getSubscriberCount() const roomACount = server.getSubscriberCount('room-a') console.log(`Total subscribers: ${total}, Room A: ${roomACount}`) }) ``` ``` -------------------------------- ### Dynamic Track Management for Media Switching Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Illustrates how to dynamically manage media tracks, including adding a video stream, switching from a camera track to a screen track, and adding screen audio as a separate stream. This is useful for scenarios like live presentations or screen sharing with audio. ```javascript const videoStream = new MediaStream() room.addStream(videoStream) // Start with camera const cameraTrack = (await navigator.mediaDevices.getUserMedia({video: true})).getVideoTracks()[0] room.addTrack(cameraTrack, videoStream) // Switch to screen const screenTrack = (await navigator.mediaDevices.getDisplayMedia({video: true})).getVideoTracks()[0] room.replaceTrack(cameraTrack, screenTrack) // Add screen audio as second stream const screenAudioStream = new MediaStream() const screenAudio = (await navigator.mediaDevices.getDisplayMedia({audio: true})).getAudioTracks()[0] room.addTrack(screenAudio, screenAudioStream) room.addStream(screenAudioStream, {metadata: {type: 'screen-audio'}}) ``` -------------------------------- ### Get Local Peer ID Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Access the `selfId` property to retrieve the unique identifier for the local peer, which is consistent across all rooms and sessions. ```javascript import {selfId} from 'trystero' console.log(`My peer ID: ${selfId}`) ``` -------------------------------- ### API Function Signature Example Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md The TypeScript signature for an API function, showing parameter types and return type. This is part of the API documentation structure. ```typescript function functionName(param1: Type1, param2?: Type2): ReturnType ``` -------------------------------- ### Add TURN Servers with turnConfig Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Extend Trystero's default STUN servers by adding your own TURN servers using the `turnConfig` array. This is useful for enabling relay connections without replacing default STUN configurations. ```javascript const config = { appId: 'my-app', turnConfig: [ { urls: ['turn:my-turn.example.com:3478', 'turn:my-turn.example.com:5349?transport=tcp'], username: 'alice', credential: 'secret123' }, { urls: 'turn:backup-turn.example.com:3478', username: 'bob', credential: 'secret456' } ] } ``` -------------------------------- ### Import joinRoom from Trystero Source: https://github.com/dmotz/trystero/blob/main/README.md Import the `joinRoom` function from the Trystero library. This function is used to establish a connection to a room. ```js import {joinRoom} from 'trystero' ``` -------------------------------- ### Import joinRoom with different strategies Source: https://github.com/dmotz/trystero/blob/main/README.md Import the `joinRoom` function from different Trystero strategy packages. This allows you to choose your preferred signaling method. ```js import {joinRoom} from '@trystero-p2p/mqtt' // or import {joinRoom} from '@trystero-p2p/torrent' // or import {joinRoom} from '@trystero-p2p/supabase' // or import {joinRoom} from '@trystero-p2p/firebase' // or import {joinRoom} from '@trystero-p2p/ipfs' // or import {joinRoom} from '@trystero-p2p/ws-relay' ``` -------------------------------- ### Get Connected Peers in Trystero Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Retrieves a map of all connected peers, excluding the local user. Useful for iterating through and interacting with individual peer connections. ```javascript const peers = room.getPeers() Object.entries(peers).forEach(([peerId, connection]) => { console.log(`Connected to ${peerId}`, connection) }) ``` -------------------------------- ### joinRoom(config, roomId, [callbacks]) Source: https://github.com/dmotz/trystero/blob/main/README.md Adds a local user to a room, enabling communication channels with other peers in the same namespace. Calling this multiple times with the same namespace returns the same room instance. ```APIDOC ## `joinRoom(config, roomId, [callbacks])` ### Description Adds local user to room whereby other peers in the same namespace will open communication channels and send events. Calling `joinRoom()` multiple times with the same namespace will return the same room instance. ### Method `joinRoom(config, roomId, [callbacks])` ### Parameters #### `config` Object - **`appId`** (string) - Required - A unique string identifying your app. For Supabase, use your project URL. For Firebase, use the `databaseURL` from your Firebase config. - **`password`** (string) - Optional - A string to encrypt session descriptions via AES-GCM. If not set, a key derived from `appId` and `roomId` is used. - **`passive`** (boolean) - Optional - For backup or relay peers that should listen for active peers without announcing themselves while a room is dormant. - **`relayConfig`** (object) - Optional (required for some strategies) - Strategy-specific relay settings: - **`urls`** (array of strings) - Optional (required for WebSocket) - Custom list of URLs for bootstrapping P2P connections (e.g., trackers, relays, brokers). - **`redundancy`** (integer) - Optional (BitTorrent, Nostr, MQTT only) - Number of default relay endpoints to connect to simultaneously. - **`manualReconnection`** (boolean) - Optional (Nostr and BitTorrent only) - Disables automatic pausing/resuming of reconnection attempts when the browser goes offline. - **`supabaseKey`** (string) - Required (Supabase only) - Your Supabase project's `anon public` API key. - **`firebaseApp`** (object) - Optional (Firebase only) - An already initialized Firebase app instance. - **`firebasePath`** (string) - Optional (Firebase only) - Path where Trystero writes matchmaking data in your database. - **`rtcConfig`** (object) - Optional - Custom `RTCConfiguration` for all peer connections. - **`trickleIce`** (boolean) - Optional - Controls whether ICE candidates are sent incrementally (`true`) or bundled with SDP (`false`). - **`turnConfig`** (array of objects) - Optional - Custom list of TURN servers to use. - **`rtcPolyfill`** (function) - Optional - A custom `RTCPeerConnection`-compatible constructor. #### `roomId` (string) - Required A string to namespace peers and events within a room. #### `callbacks` (function) - Optional Callback function. ``` -------------------------------- ### Dynamically Join Room with Different Strategies Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Use this pattern to allow users to select a peer-to-peer strategy at runtime. It dynamically imports the chosen strategy package and joins a room using its specific joinRoom function. ```javascript // User selects strategy const strategyPackages = { 'nostr': 'trystero', 'torrent': '@trystero-p2p/torrent', 'mqtt': '@trystero-p2p/mqtt', 'firebase': '@trystero-p2p/firebase', 'supabase': '@trystero-p2p/supabase' } async function joinRoom(strategyName, config, roomId) { const pkgName = strategyPackages[strategyName] const {joinRoom: join} = await import(pkgName) return join(config, roomId) } // Usage const room = await joinRoom('nostr', {appId: 'my-app'}, 'room-1') ``` -------------------------------- ### Listen for Peer Join Events Source: https://github.com/dmotz/trystero/blob/main/README.md Set up a callback to be notified when a new peer joins the room. The callback receives the peer's ID. ```javascript room.onPeerJoin = peerId => console.log(`${peerId} joined`) ``` -------------------------------- ### Get Relay WebSocket Connections Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md Use `getRelaySockets` to obtain an object mapping relay server URLs to their active WebSocket connections. This function is only available for strategies that utilize relay servers. ```javascript import {getRelaySockets} from '@trystero-p2p/torrent' const sockets = getRelaySockets() console.log(Object.keys(sockets)) // ['wss://tracker.webtorrent.dev', ...] ``` -------------------------------- ### Getting Server Address Information Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md Retrieve the server's bound address and port using the `address()` method. Check if the address is an object containing host and port details before logging. ```javascript const server = createWsRelayServer({port: 8080}) server.ready.then(() => { const addr = server.address() if (addr && typeof addr === 'object') { console.log(`Listening on ${addr.address}:${addr.port}`) } }) ``` -------------------------------- ### Listen for Peer Media Streams Source: https://github.com/dmotz/trystero/blob/main/README.md Set up a callback to handle incoming audio/video streams from other peers. The callback receives the stream and the peer's ID. ```javascript room.onPeerStream = (stream, peerId) => (peerElements[peerId].video.srcObject = stream) ``` -------------------------------- ### Configure TURN Server Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md Add a TURN server configuration to your Trystero app to help peers behind restrictive firewalls or NATs establish connections. ```javascript const config = { appId: 'my-app', turnConfig: [ { urls: 'turn:turn.example.com:3478', username: 'user', credential: 'pass' } ] } ``` ```javascript const config = { appId: 'my-app', turnConfig: [ { urls: [ 'turn:turn.cloudflare.com?transport=udp', 'turn:turn.cloudflare.com?transport=tcp' ], username: await getCloudflareUsername(), credential: await getCloudflareCredential() } ] } ``` -------------------------------- ### Handling Join Errors in Trystero Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md This snippet demonstrates how to handle join errors by checking the error message within the onJoinError callback. It provides specific examples for password mismatches and connection issues. ```javascript const room = joinRoom({appId: 'my-app'}, 'room-1', { onJoinError: ({error, peerId}) => { if (error.includes('password')) { console.error('Password mismatch with', peerId) // Notify user to verify shared secret } else if (error.includes('connection')) { console.error('Network issue connecting to', peerId) // May need TURN server configuration } } }) ``` -------------------------------- ### Get Relay Socket Connections Source: https://github.com/dmotz/trystero/blob/main/README.md Retrieve an object mapping relay URLs to their WebSocket connections. This is available for BitTorrent, Nostr, MQTT, and WebSocket relay types and can help diagnose connection states. ```javascript import {getRelaySockets} from '@trystero-p2p/torrent' console.log(getRelaySockets()) // => Object { // "wss://tracker.webtorrent.dev": WebSocket, // "wss://tracker.openwebtorrent.com": WebSocket // } ``` -------------------------------- ### Join Room with Nostr Strategy Configuration Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Demonstrates how to join a Trystero room using the default Nostr signaling strategy. It shows how to configure the number of relays to connect to for redundancy. ```javascript import {joinRoom} from 'trystero' const room = joinRoom({ appId: 'my-app-v1', relayConfig: { redundancy: 3 // Connect to 3 relays instead of default 5 } }, 'room-1') room.onPeerJoin = peerId => console.log(`${peerId} joined`) ``` -------------------------------- ### Send and Receive Multiple Streams Per Peer Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Demonstrates how to send both audio and screen streams to a peer and how to identify and handle incoming streams based on metadata. Ensure you have the necessary media devices (microphone, display) available. ```javascript const audioStream = await navigator.mediaDevices.getUserMedia({audio: true}) const screenStream = await navigator.mediaDevices.getDisplayMedia({video: true}) // Send both room.addStream(audioStream, {metadata: {type: 'microphone'}}) room.addStream(screenStream, {metadata: {type: 'screen'}}) // Receive and identify const peerStreams = {} room.onPeerStream = (stream, peerId, metadata) => { if (!peerStreams[peerId]) { peerStreams[peerId] = {} } const type = metadata?.type || 'unknown' peerStreams[peerId][type] = stream if (type === 'microphone') { const audio = new Audio() audio.srcObject = stream audio.play() } else if (type === 'screen') { const video = document.getElementById(`screen-${peerId}`) video.srcObject = stream } } ``` -------------------------------- ### Processing requestMany() Results Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md Illustrates how to handle results from the requestMany() method, which returns an array of PeerResult objects instead of throwing errors. This example shows filtering results by status (fulfilled, timeout, rejected, disconnected) and logging responses. ```typescript type PeerResult = | {peerId: string; status: 'fulfilled'; value: R} | {peerId: string; status: 'timeout'} | {peerId: string; status: 'rejected'; error: Error} | {peerId: string; status: 'disconnected'} ``` ```javascript const action = room.makeAction('poll', { kind: 'request', onRequest: ({question}) => question === 'ready' ? 'yes' : 'no' }) const results = await action.requestMany( {question: 'ready'}, { targets: [alice, bob, charlie], timeoutMs: 3000, onResult: (result) => { if (result.status === 'fulfilled') { console.log(`${result.peerId} answered: ${result.value}`) } } } ) // Process all results const fulfilled = results.filter(r => r.status === 'fulfilled') const timedOut = results.filter(r => r.status === 'timeout') const rejected = results.filter(r => r.status === 'rejected') const disconnected = results.filter(r => r.status === 'disconnected') console.log(`${fulfilled.length} responded, ${timedOut.length} timed out`) ``` -------------------------------- ### Import Supabase Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Import necessary functions for using the Supabase strategy. ```javascript import {joinRoom, selfId} from '@trystero-p2p/supabase' ``` -------------------------------- ### Import Firebase Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Import the necessary functions for joining a room using the Firebase strategy. ```javascript import {joinRoom, selfId} from '@trystero-p2p/firebase' ``` -------------------------------- ### Import IPFS Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Import necessary functions for using the IPFS strategy. ```javascript import {joinRoom, selfId} from '@trystero-p2p/ipfs' ``` -------------------------------- ### Import MQTT Strategy Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md Imports necessary functions for the MQTT signaling strategy. ```javascript import {joinRoom, selfId, getRelaySockets} from '@trystero-p2p/mqtt' ``` -------------------------------- ### Send Binary Data with Metadata Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md Use `room.makeAction('file')` to create an action for sending binary data. Attach metadata to describe the file's properties like name, type, and size. ```javascript const file = room.makeAction('file') const blob = /* ... */ const metadata = { name: 'document.pdf', type: 'application/pdf', size: blob.size } await file.send(blob, {metadata}) ``` -------------------------------- ### MQTT Broker Configuration Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md Configure MQTT brokers with custom URLs and redundancy. All URLs must support WebSocket (wss://). Use this for MQTT-based P2P communication. ```javascript import {joinRoom} from '@trystero-p2p/mqtt' const config = { appId: 'my-app-id', relayConfig: { urls: ['wss://broker.emqx.io:8084/mqtt'], redundancy: 2 } } ``` -------------------------------- ### joinRoom Source: https://github.com/dmotz/trystero/blob/main/README.md Joins a specified room with optional callbacks for connection events. This is the primary method for establishing a connection to a room. ```APIDOC ## joinRoom(config, roomId, [callbacks]) ### Description Joins a specified room with optional callbacks for connection events. This is the primary method for establishing a connection to a room. ### Parameters #### Path Parameters - **config** (object) - Required - Configuration object for the connection strategy. - **roomId** (string) - Required - The identifier of the room to join. - **callbacks** (object) - Optional - An object containing callback functions for various events. ```