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

@statewalker/webrun-streams-webrtc

v0.1.2

Published

WebRTC DataChannel-backed Connect/Serve adapter (native multi-stream) in the webrun-streams-* family

Readme

@statewalker/webrun-streams-webrtc

WebRTC Connect / Serve adapter in the webrun-streams-* family, with native multi-stream — one RTCDataChannel per logical call.

What this is

A binding between an RTCPeerConnection and the webrun-streams Duplex seam. Your handler is an ordinary Duplex — (input: AsyncIterable<Uint8Array>) => AsyncGenerator<Uint8Array> — and this package carries it directly between two browsers with no server in the data path.

Unlike the message-oriented adapters (WebSocket, MessagePort, LiveKit, PeerJS), this one does not use emulateMux. WebRTC can open as many data channels as you want, so each call(input) opens its own RTCDataChannel and the responder picks it up via pc.ondatachannel. Concurrency is the transport's, not emulated.

Why it exists

RTCDataChannel is a good byte pipe with two gaps that every user hits:

  1. No half-close. A channel is open or closed; there is no way to say "I'm done sending, keep receiving". Request/response needs exactly that.
  2. No error channel. If the far end throws, the near end sees a closed channel and no reason.

This adapter closes both gaps with a one-byte frame header inside each data channel message:

| Byte | Frame | Payload | | --- | --- | --- | | 0x00 | DATA | body bytes | | 0x01 | END | — (half-close) | | 0x02 | ERROR | serialised Error (message, stack, custom fields) |

Outbound bytes are chunked at 16 KiB to stay inside the SCTP message limits that browsers enforce.

Install

npm install @statewalker/webrun-streams-webrtc

No peer dependencies. In the browser RTCPeerConnection is built in; in Node tests it is supplied by @roamhq/wrtc.

Getting started

Signalling, auth and connection setup are the caller's responsibility. This package takes an already-open RTCPeerConnection and does nothing else. If you need signalling too, see @statewalker/webrun-streams-signaling, which produces connected peers for you.

Responder side — register a handler:

import { serve } from "@statewalker/webrun-streams-webrtc";

const stop = await serve({ pc }, async function* echo(input) {
  for await (const chunk of input) yield chunk;
});

Caller side — open calls over the same peer connection:

import { connect } from "@statewalker/webrun-streams-webrtc";

const { call, close } = await connect({ pc });

for await (const chunk of call([new TextEncoder().encode("ping")])) {
  console.log(new TextDecoder().decode(chunk)); // "ping"
}

await close();

Concurrent calls

Every call(...) gets its own data channel, so calls are genuinely parallel:

import { collectBytes } from "@statewalker/webrun-streams";

const [a, b] = await Promise.all([
  collectBytes(call(requestA)),
  collectBytes(call(requestB)),
]);

Carrying HTTP over it

Pair with webrun-http-streams to exchange real Request / Response objects — including streaming bodies and SSE — directly between two browsers:

import { fetchOverDuplex } from "@statewalker/webrun-http-streams";

const response = await fetchOverDuplex(call, new Request("http://peer/api/events"));

See apps/p2p-demo for this running end to end.

API

connect(params): Promise<{ call, close }>

Type: Connect<WebRtcParams>.

| Field | Type | Meaning | | --- | --- | --- | | pc | RTCPeerConnection | An already-open peer connection. |

Each call(input) opens a fresh RTCDataChannel. close() tears down the adapter's channels; it does not close pc, which you own.

serve(params, handler): Promise<() => Promise<void>>

Type: Serve<WebRtcParams>. Listens on pc.ondatachannel and runs handler for each inbound channel. Returns an idempotent teardown.

duplexOverDataChannel(channel, options?): Duplex

The lower-level primitive: wraps a single RTCDataChannel as one Duplex, implementing the DATA/END/ERROR framing described above. Use it when you manage channel creation yourself.

WebRtcParams

The parameter type shared by connect and serve.

Conformance

Runs @statewalker/webrun-streams-conformance against a real RTCPeerConnection pair — concurrency, half-close, mid-stream cancellation, error propagation and idempotent teardown.

The suite is browser-gated: tests/conformance.test.ts checks for a window global and registers the suite only there, so the plain Node run reports it as skipped.

pnpm --filter @statewalker/webrun-streams-webrtc test:browser   # runs the suite
pnpm --filter @statewalker/webrun-streams-webrtc test           # reports it skipped

Dependencies

| Dependency | Kind | Why | | --- | --- | --- | | @statewalker/webrun-streams | runtime | The Duplex seam and error serialisation. | | @roamhq/wrtc | dev | RTCPeerConnection for the Node conformance run. |

No runtime dependencies outside the workspace. ESM only ("type": "module").

License

MIT © statewalker — see LICENSE.