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

freertc

v0.1.33

Published

Cloudflare Worker signaling relay for WebRTC peers with D1 storage.

Readme

freertc Cloudflare Worker (WebSocket + D1)

This project provides a Cloudflare Worker signaling relay for WebRTC peers using the Peer Signaling Protocol (PSP) envelope shape.

Install from npm

Local project install:

npm install freertc

Global install:

npm install -g freertc

When you run the CLI from your project directory, freertc copies the required worker files into that directory on first run:

  • src/index.js
  • public/index.html
  • public/app.js
  • scripts/d1-schema.sql
  • wrangler.template.jsonc
  • wrangler.workers-dev.jsonc

What this worker does

  • Accepts WebSocket client connections at /ws.
  • Validates PSP message envelopes (psp_version, type, network, from, message_id, timestamp).
  • Supports discovery, negotiation, control, and extension message types.
  • Stores peer announcements in Cloudflare D1 (psp_announcements).
  • Stores directed signaling messages in Cloudflare D1 (psp_relay).
  • Exposes a simple relay registry at /api/v1/relays when D1 is configured.
  • Delivers queued relay messages when peers reconnect.
  • Serves the browser demo from public/.

Runtime scope

  • The checked-in Cloudflare Worker runtime is src/index.js with Cloudflare D1 (DB binding).
  • The Rust/WASM worker lives in src/lib.rs and is optional; the default template now uses the JS worker path.
  • The built-in browser demo served by the Worker is public/index.html + public/app.js.
  • src/kv.js and demo/src/* are legacy/experimental code paths and are not used by wrangler dev or wrangler deploy in the current setup.

Supported message types

  • Discovery: announce, withdraw, discover, peer_list, redirect
  • Negotiation: connect_request, connect_accept, connect_reject, offer, answer, ice_candidate, ice_end, renegotiate
  • Control: ping, pong, bye, error, ack
  • Extension: ext

Wrangler install wizard (recommended)

Use the interactive wizard from the project directory where you want the worker files and Wrangler config to live:

npx freertc wizard

The default command runs full setup mode (both):

npx freertc

You can also preselect full setup mode explicitly:

npx freertc setup

Global install flow:

freertc wizard
freertc

After install, freertc prints a quick-start reminder with the exact next command.

The wizard can:

  • Copy the worker runtime files into your current project when they are missing.
  • Verify Wrangler CLI.
  • Create wrangler.jsonc from wrangler.template.jsonc if needed.
  • No domain? No problem. Press Enter at the domain prompt to deploy on a free workers.dev subdomain.
  • Set Worker name automatically to freertc-<your-domain> when a domain is provided.
  • Initialize local D1 schema for wrangler dev.
  • Initialize remote D1 schema for deploy.
  • Detect Rust build configs and install worker-build/WASM target automatically when required.
  • Check existing Wrangler auth and only run wrangler login when needed.
  • Optionally run npm run dev:cf and npm run deploy.

Manual setup

1. Install dependencies

npm install

If you installed the npm package instead of cloning the repo, use npx freertc wizard instead of the repository scripts below.

2. Configure Wrangler

  • If needed, copy wrangler.template.jsonc to wrangler.jsonc.
  • Set your Worker name, route(s), and D1 database values.
  • Ensure d1_databases[0].binding is DB.

3. Initialize D1 schema

Local (for wrangler dev):

npm run d1:init:local

Remote (for production):

npm run d1:init:remote

If your database name is not freertc-signal, use Wrangler directly:

wrangler d1 execute <your-db-name> --local --file scripts/d1-schema.sql
wrangler d1 execute <your-db-name> --remote --file scripts/d1-schema.sql

Local development

npm run dev

npm run dev now runs the non-Cloudflare local runtime (plain Node.js + WebSocket).

Cloudflare/Wrangler runtime:

npm run dev:cf

Shortcut alias (same behavior):

npm run dev:local

You can also choose host/port:

HOST=127.0.0.1 PORT=8788 npm run dev:node

npm run dev:cf checks local Rust Worker prerequisites automatically:

  • Uses wrangler.workers-dev.jsonc automatically when wrangler.jsonc is not present.
  • Only installs worker-build and the WebAssembly Rust target when the selected Wrangler config uses a worker-build command.
  • The checked-in wrangler.workers-dev.jsonc now points to src/index.js, so standard demo runs do not require Rust/WASM setup.

Endpoints:

  • WebSocket: ws://127.0.0.1:8788/ws (npm run dev)
  • Health: http://127.0.0.1:8788/health (npm run dev)
  • Demo UI: http://127.0.0.1:8788/ (npm run dev)

Cloudflare/Wrangler endpoints (default):

  • WebSocket: ws://127.0.0.1:8787/ws (npm run dev:cf)
  • Health: http://127.0.0.1:8787/health (npm run dev:cf)
  • Demo UI: http://127.0.0.1:8787/ (npm run dev:cf)
  • Relay registry: http://127.0.0.1:8787/api/v1/relays (GET/POST, when D1 is configured)

Deploy

npx freertc deploy

If you installed freertc globally:

freertc deploy

Repository-only scripts:

  • npm run build builds the Rust/WASM worker via worker-build --release.
  • npm run deploy:raw deploys without --env production.
  • npm run check runs cargo check --target wasm32-unknown-unknown for the Rust worker path.
  • npm run dev runs the standalone local relay (non-Cloudflare).
  • npm run dev:cf runs Wrangler/Cloudflare local dev.
  • npm run dev:node runs a standalone local relay without Cloudflare/Wrangler.
  • npm run dev:local is a no-env shortcut for the standalone local relay.

Troubleshooting custom domain deploys

If your custom domain returns:

{"error":"API key is missing"}

that error is usually from Cloudflare routing/auth config, not from this Worker runtime.

Quick checks:

  1. Compare https://<workers-subdomain>/health and https://<custom-domain>/health.
  2. Confirm your route/custom domain points to this Worker.
  3. Review Cloudflare Access/API Shield/WAF rules on the custom hostname.
  4. If deploying with --env production, verify that environment is the one bound to the route.

Expected /health response includes JSON like:

{"ok":true,"version":"0.1.33","protocol_version":"1.0","peers":0}

Auto WebRTC two-tab test

The demo defaults to Auto WebRTC and performs real offer/answer + ICE exchange over this Worker.

  1. Open http://127.0.0.1:8787/ in two tabs.
  2. Set both tabs to the same network and session_id.
  3. Set opposite peer IDs using random hex strings:
    • Tab A from: fc2142e44ec5c76f1bd46ccbb1eb2ed48f66f64260a5299c871f37ac742fa0c9
    • Tab B from: 3e45d44c4ce4f9304a53f42b978fd13d23f85df4d97a88f8eb33ec13a2f8f7b1
  4. Set each tab to to the other tab from, or leave to empty for auto-discovery.
  5. Connect both sockets and click Start Auto Handshake in both tabs.
  6. When DataChannel is open, send chat messages.

Minimal client expectations

  • Send announce first to bind socket identity (from, network).
  • Include session_id for negotiation messages.
  • Include to for directed messages.
  • Use periodic announce to refresh presence TTL and receive queued relay messages.
  • Use ping for liveness (pong) and keepalive.

Notes

  • TTL is enforced using timestamp + ttl_ms (default 30 seconds, max 120 seconds).
  • Malformed envelopes produce PSP error responses.