peer
@noy-db/by-peer·pnpm add @noy-db/by-peer @noy-db/hubSyncs an unlocked vault directly between two browsers or Node processes over a WebRTCDataChannel— 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.