anchordb-relay
v1.3.2
Published
Development-only relay that brokers Anchor Inspector connections between a mobile app and Anchor Lens.
Maintainers
Readme
anchordb-relay
Development-only relay that lets Anchor Lens open the database of an app running AnchorDB — on a phone, an emulator or a browser.
Overview · Report a bug or get support
npx anchor-relay --host 0.0.0.0 --room my-appAnchor Inspector Relay
──────────────────────
listening ws://0.0.0.0:9440
room my-app
The app — inspector.relayUrl, or connectInspectorToRelay({ relayUrl }):
ws://192.168.1.24:9440/relay?room=my-app&role=agent
Anchor Lens — scan, or paste the link:
▄▄▄▄▄▄▄ ▄▄▄ ▄ ▄▄▄▄▄▄▄
█ ▄▄▄ █ …QR code… █
anchor-lens://connect?relay=ws%3A%2F%2F192.168.1.24%3A9440%2Frelay%3Froom%3Dmy-app%26role%3Dclient&room=my-appOpen an app in Lens
1. Run the relay where the phone can reach it — same Wi-Fi, and --host 0.0.0.0. The default
127.0.0.1 is reachable only from the computer itself.
2. Publish the app's database with the agent URL the relay printed:
export const db = createAnchorDB({
name: "my-app",
inspector: {
enabled: true,
relayUrl: "ws://192.168.1.24:9440/relay?room=my-app&role=agent",
onPairing: ({ code }) => showPairingCode(code), // or listen for the "inspector:pairing" event
},
});The database connects on construction, stays connected, and reconnects when the phone sleeps or the
relay restarts. To connect later instead — from a settings screen, say — call
connectInspectorToRelay(db, { relayUrl, onPairing }) from anchordb.
3. In Lens, scan the QR code, then type the pairing code the app is showing. Nothing else is typed: the challenge the code is signed against arrives from the app.
--room keeps the room the same across restarts, so the URL built into the app keeps working. Without
it the room is random each time.
Android release builds
The relay speaks plain ws://, which Android blocks in release builds. Allow it in a build meant for
inspection — in Expo, with expo-build-properties:
["expo-build-properties", { "android": { "usesCleartextTraffic": true } }]A release build also refuses to start the inspector unless allowInProduction: true is set, so an
inspector left on cannot ship by accident.
Options
| Flag | Default | |
| --- | --- | --- |
| --host | 127.0.0.1 | 0.0.0.0 to reach it from a phone |
| --port | 9440 | |
| --room | random | a fixed room id, 4–64 letters, digits, _ or - |
| --mongo-bridge | off | see below |
Why a relay exists
React Native and browsers can open a WebSocket client but cannot listen without a native TCP module — which would force an Expo dev build and rule out Expo Go entirely. So both the app and Lens dial out to this small Node process, which pairs them by room and copies frames across.
It is a dumb pipe on purpose: it never parses the inspector protocol, so the protocol can change without the relay ever needing an update.
What it deliberately does not do
It does not authenticate the inspector session. Pairing is end-to-end between the app and Lens: Lens proves it knows the code with an HMAC over the app's challenge. The code is never sent, so a compromised or malicious relay still cannot issue itself a session, and the room id only decides who is connected to whom.
The QR payload carries the relay address and room — never the pairing code, which only the app displays. Photographing the screen is therefore not enough to pair.
The MongoDB bridge
npm install mongodb # an optional dependency, installed where the relay runs
npx anchor-relay --mongo-bridgeAnchor Lens can move collections between a device and a real MongoDB, but it cannot open the
connection itself: the driver needs raw TCP and TLS sockets, and React Native has neither. So the
driver runs here, and Lens drives it over /bridge:
pull: relay reads MongoDB ──Extended JSON──► agent.importCollection()
push: agent.exportCollection() ──Extended JSON──► relay writes MongoDBBoth hops carry Extended JSON — the interchange format anchordb already cross-validates
against the official bson package — so an ObjectId is still an ObjectId at the far end.
Three restrictions, and why
- Off unless you ask for it. A relay that will dial any MongoDB on request is a confused deputy: every process on the machine could use it to reach a database it has no credentials for.
- The room is the token. A bridge socket must present the room id the relay printed.
- The connection string is never stored and never logged. It lives in one
MongoClientfor the life of one socket and dies with it, and every log line and error message goes throughredactMongoUri.
--host 0.0.0.0 together with --mongo-bridge is a combination worth thinking twice about.
Safety
Binds to 127.0.0.1 by default. A relay reachable from the whole network is a database reachable
from the whole network, so --host 0.0.0.0 is a deliberate opt-in and prints a warning.
Development only. Never run this in production.
API
import { InspectorRelay, startRelayServer } from "anchordb-relay";
const server = await startRelayServer({ port: 9440, host: "0.0.0.0" });
const room = server.relay.createRoom("MyApp", { id: "my-app", keep: true });InspectorRelay is transport-agnostic and has no ws dependency, so the routing logic can be
driven by any socket implementation — or tested without opening a port.
Status
1.2.0. MIT.
Tested: room routing and isolation, frame limits, kept and chosen rooms, and a whole session over real sockets — a relay server, an app publishing itself, and a Lens client that pairs with only the code, reads and writes, then shuts down cleanly. The MongoDB bridge is tested against an injected fake driver; its driver calls have never run against a live MongoDB.
The AnchorDB family
Six packages. Only anchordb is required — the rest exist so that an offline-only app never
has to download Express, and an Express server never has to download React.
| Package | What it is | Runs where |
| --- | --- | --- |
| anchordb | The database — schema, models, queries, aggregation, optional sync | phone · browser · Node |
| anchordb-react | React and React Native hooks | the device |
| anchordb-angular | Angular / Ionic module, DI and RxJS observables | the device |
| anchordb-sync-server | Server half of sync — Express, NestJS, Next.js | your backend |
| anchordb-relay (this package) | Dev relay for the Anchor Lens inspector | your laptop |
| anchordb-lens-link | Open a QA build's database in Anchor Lens on the same phone, from a file | the device, in QA builds |
Each one needs a different third-party framework as a peer dependency, and npm resolves those per package rather than per import — which is why they are not one package. Full reasoning and API reference: github.com/knnadeera/anchordb.
Bugs, support and feedback
Report a bug, ask for help or suggest a feature on the AnchorDB project page —
choose anchordb-relay as the package, and the reply comes by email.
Include the version (npm ls anchordb), where it runs, the smallest snippet that reproduces it, and
the full error.
