Problem
wrtc@0.4.7 was last published 2023-10-12 and has never actually worked in this
repo. require("wrtc") fails with Cannot find module '../build/Release/wrtc.node' —
the native binding was never built. Both server specs vi.mock("wrtc", …), so nothing
ever loaded it.
It also breaks pnpm install for everyone: wrtc ships node-pre-gyp as a
bundledDependency, which pnpm's content-addressable store does not reconstitute, so
its install script dies with node-pre-gyp: command not found. That failure masked
unrelated build errors across the whole workspace.
Candidates evaluated
| lib |
Node 26 |
Bun 1.4 |
notes |
wrtc |
✗ |
✗ |
unmaintained since 2023, no native binding |
@roamhq/wrtc |
✓ |
panic |
unsupported uv function: uv_async_init (oven-sh/bun#18546) |
node-datachannel |
✓ |
✓ |
chosen |
werift |
✓ |
✓ |
pure TS, kept as fallback only |
@roamhq/wrtc passes on Node and hard-crashes on Bun — a Node-only CI would have
greenlit it.
Decision: node-datachannel
- libdatachannel bindings; N-API 8, so ABI-stable across Node majors
- platform
optionalDependencies, no install script — removes the failure class entirely
- 8.3 MB native binary vs 24 MB for the libwebrtc-based forks
node-datachannel/polyfill implements the W3C API, so the swap is one import line
Scope
- Remove
wrtc, @mapbox/node-pre-gyp, and the allowBuilds: wrtc entry
- Delete
src/server/wrtc.d.ts (declare module "wrtc" typed the whole module any);
udp.server.network.ts gets type-checked for the first time
- Add NAT support, since the lib swap is the moment to do it:
ICE_SERVERS — JSON array of STUN/TURN servers
ICE_PORT — fixed port + ICE UDP mux, so every peer shares one port instead of a
random one each (this is what broke the multi-pod Kubernetes setup)
ADVERTISE_IP — public address written into typ host candidates; srflx
candidates are left alone since STUN already resolved them
All three default to off; current behaviour is unchanged without them.
Problem
wrtc@0.4.7was last published 2023-10-12 and has never actually worked in thisrepo.
require("wrtc")fails withCannot find module '../build/Release/wrtc.node'—the native binding was never built. Both server specs
vi.mock("wrtc", …), so nothingever loaded it.
It also breaks
pnpm installfor everyone: wrtc shipsnode-pre-gypas abundledDependency, which pnpm's content-addressable store does not reconstitute, soits install script dies with
node-pre-gyp: command not found. That failure maskedunrelated build errors across the whole workspace.
Candidates evaluated
wrtc@roamhq/wrtcunsupported uv function: uv_async_init(oven-sh/bun#18546)node-datachannelwerift@roamhq/wrtcpasses on Node and hard-crashes on Bun — a Node-only CI would havegreenlit it.
Decision:
node-datachanneloptionalDependencies, no install script — removes the failure class entirelynode-datachannel/polyfillimplements the W3C API, so the swap is one import lineScope
wrtc,@mapbox/node-pre-gyp, and theallowBuilds: wrtcentrysrc/server/wrtc.d.ts(declare module "wrtc"typed the whole moduleany);udp.server.network.tsgets type-checked for the first timeICE_SERVERS— JSON array of STUN/TURN serversICE_PORT— fixed port + ICE UDP mux, so every peer shares one port instead of arandom one each (this is what broke the multi-pod Kubernetes setup)
ADVERTISE_IP— public address written intotyp hostcandidates;srflxcandidates are left alone since STUN already resolved them
All three default to off; current behaviour is unchanged without them.