stable

peer

WebRTC peer-to-peer transport that carries encrypted envelopes directly between two noy-db instances, with no relay server in the middle.

@noy-db/by-peer · pnpm add @noy-db/by-peer @noy-db/hub Syncs an unlocked vault directly between two browsers or Node processes over a WebRTC DataChannel — no server in the middle.

What it does

@noy-db/by-peer opens a WebRTC DataChannel between two peers and carries noy-db's encrypted envelopes across it — any TURN relay in the path only ever sees AES-256-GCM ciphertext. peerStore() wraps the far end as a NoydbStore that RPCs every operation to the remote peer; servePeerStore() runs on the other side and answers those RPCs against a local store. peerStore() also slots into createNoydb's sync option as a SyncTarget with role: 'sync-peer', pairing with the sync and crdt services for collaborative editing. createOffer() / acceptOffer() are thin SDP handshake helpers — signaling itself (how the offer/answer blobs travel) is left to the caller: QR code, chat message, pastebin, whatever fits.

servePeerStore accepts an allow whitelist to expose a read-only or append-only peer, and a leaderElection option (Web Locks API) so that when 3+ tabs share a channel — typically via @noy-db/by-tabs — only one tab answers RPCs at a time.

Usage

import { createNoydb } from '@noy-db/hub'
import { toBrowserIdb } from '@noy-db/to-browser-idb'
import { peerStore, createOffer, acceptOffer } from '@noy-db/by-peer'

// Peer A — initiator
const initiator = await createOffer()
shareWithPeerB(initiator.offer)             // QR code, Matrix, pastebin, …
await initiator.accept(await receiveAnswer())
const channel = await initiator.channel

const db = await createNoydb({
  store: toBrowserIdb(),
  sync: { store: peerStore({ channel }), role: 'sync-peer' },
})

Peer B mirrors the handshake with acceptOffer() and runs servePeerStore({ channel, store }) so its local store answers the incoming RPC calls.

See also