Initial Commit
This commit is contained in:
140
packages/networking/network/network-trystero-server/README.md
Normal file
140
packages/networking/network/network-trystero-server/README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# @suaveplan/network-trystero-server - Server-tier Trystero signaling daemon — hosts an MQTT broker shim or Nostr relay shim over plain WebSocket for browser-tier @suaveplan/network-discovery-trystero clients. Construction-time mode selection, injectable broker factory, AbortSignal lifecycle, health/ready/live endpoints, OTel observability, real-fake integration tests.
|
||||
|
||||
## Summary
|
||||
|
||||
Server-tier Trystero signaling daemon. Hosts an MQTT-style or
|
||||
Nostr-style WebSocket broker shim plus standard `/health` / `/ready` /
|
||||
`/live` probes on a single Node `http.Server`. Browser-tier clients
|
||||
running `@suaveplan/network-discovery-trystero` connect to the
|
||||
daemon's published `relayUrl` for relay-backed P2P signaling.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [broker-select](./src/server/broker-select.md) — The broker-select module resolves which broker factory the daemon hosts and bundles the matching mode-specific options…
|
||||
- [health-listener](./src/server/health-listener.md) — The health-listener helper extracts the `http.Server.listen` promise adapter out of the main daemon module so the daemo…
|
||||
- [peer-events](./src/server/peer-events.md) — The peer-events module owns the daemon-side wiring of broker lifecycle callbacks into the daemon's connection table, OT…
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
<!-- end:auto-docs --> - [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [broker-select](./src/server/broker-select.md) — The broker-select module resolves which broker factory the daemon hosts and bundles the matching mode-specific options…
|
||||
- [health-listener](./src/server/health-listener.md) — The health-listener helper extracts the `http.Server.listen` promise adapter out of the main daemon module so the daemo…
|
||||
- [peer-events](./src/server/peer-events.md) — The peer-events module owns the daemon-side wiring of broker lifecycle callbacks into the daemon's connection table, OT…
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [broker-select](./src/server/broker-select.md) — The broker-select module resolves which broker factory the daemon hosts and bundles the matching mode-specific options…
|
||||
- [health-listener](./src/server/health-listener.md) — The health-listener helper extracts the `http.Server.listen` promise adapter out of the main daemon module so the daemo…
|
||||
- [peer-events](./src/server/peer-events.md) — The peer-events module owns the daemon-side wiring of broker lifecycle callbacks into the daemon's connection table, OT…
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [broker-select](./src/server/broker-select.md) — The broker-select module resolves which broker factory the daemon hosts and bundles the matching mode-specific options…
|
||||
- [health-listener](./src/server/health-listener.md) — The health-listener helper extracts the `http.Server.listen` promise adapter out of the main daemon module so the daemo…
|
||||
- [peer-events](./src/server/peer-events.md) — The peer-events module owns the daemon-side wiring of broker lifecycle callbacks into the daemon's connection table, OT…
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/errors.md) — <!-- begin:auto-docs --> _(no submodules)_- [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_ - [health](./src/health/health.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_ - [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_ - [broker-select](./src/server/broker-select.md) — The broker-select module resolves which broker factory the daemon hosts and bundles the matching mode-specific options…
|
||||
- [health-listener](./src/server/health-listener.md) — The health-listener helper extracts the `http.Server.listen` promise adapter out of the main daemon module so the daemo…
|
||||
- [peer-events](./src/server/peer-events.md) — The peer-events module owns the daemon-side wiring of broker lifecycle callbacks into the daemon's connection table, OT…
|
||||
- [server](./src/server/server.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||||
## Why this package
|
||||
|
||||
- **One daemon, one mode.** Construction-time selection between
|
||||
`"mqtt"` and `"nostr"`. No runtime branching past the broker
|
||||
factory, so dashboards split cleanly by `mode` label.
|
||||
- **Defensive by default.** Malformed frames flow through
|
||||
`onMalformedFrame` and increment
|
||||
`trystero_server.messages_relayed_total{outcome="error"}` without
|
||||
ever crashing the relay.
|
||||
- **Injection-friendly.** The broker shim is a peer dependency on
|
||||
intent — production wires a real WebSocket broker, tests bind a
|
||||
deterministic in-memory `FakeBroker`.
|
||||
- **Lifecycle-correct.** `start({ signal? })` resolves with
|
||||
`{ address, port, mode, relayUrl }`. `stop()` is idempotent and
|
||||
drains in-flight peers.
|
||||
|
||||
## Run the daemon
|
||||
|
||||
```ts
|
||||
import {
|
||||
TrysteroServer,
|
||||
type BrokerFactory,
|
||||
} from "@suaveplan/network-trystero-server";
|
||||
|
||||
const mqttBrokerFactory: BrokerFactory = (deps) => {
|
||||
// attach to the daemon's http.Server, handle WS upgrade, etc.
|
||||
return {
|
||||
mode: deps.mode,
|
||||
activeConnections: 0,
|
||||
async start({ httpServer, callbacks }) {
|
||||
// real broker wiring
|
||||
},
|
||||
async stop() {
|
||||
// drain sockets, close listeners
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const server = new TrysteroServer({
|
||||
mode: "mqtt",
|
||||
port: 8765,
|
||||
host: "0.0.0.0",
|
||||
maxConnections: 256,
|
||||
mqttBrokerFactory,
|
||||
});
|
||||
|
||||
const { relayUrl } = await server.start();
|
||||
console.log(`trystero relay listening on ${relayUrl}`);
|
||||
|
||||
process.on("SIGTERM", async () => {
|
||||
await server.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
```
|
||||
|
||||
## Modes
|
||||
|
||||
| Mode | Wire path | Mode-specific options |
|
||||
|---------|------------|------------------------------------|
|
||||
| `mqtt` | `/mqtt` | `{ password? }` |
|
||||
| `nostr` | `/nostr` | `{ relayName? }` |
|
||||
|
||||
Both modes follow the same wire-formatting contract from the
|
||||
browser-tier companion package
|
||||
[`@suaveplan/network-discovery-trystero`](../network-discovery-trystero) —
|
||||
the daemon publishes the matching `relayUrl` and the discovery client
|
||||
treats it as a relay endpoint.
|
||||
|
||||
## Configuration reference
|
||||
|
||||
See [`src/types/types.md`](./src/types/types.md) for the full strict
|
||||
`TrysteroServerConfig`. The only required fields are `mode`, `port`,
|
||||
and the per-mode broker factory. Every other field is optional with
|
||||
a spec-documented default.
|
||||
|
||||
## Health endpoints
|
||||
|
||||
| Verb | 200 OK when | 503 when |
|
||||
|----------|--------------------------------------|--------------------------------------|
|
||||
| `/live` | process alive (always, until stop) | after `stop()` |
|
||||
| `/ready` | started AND below `maxConnections` | starting, at-cap, or stopped |
|
||||
| `/health`| started AND below `maxConnections` | starting, at-cap, or stopped |
|
||||
|
||||
See [`src/health/health.md`](./src/health/health.md).
|
||||
|
||||
## Observability
|
||||
|
||||
OpenTelemetry instrument names emitted by the daemon:
|
||||
|
||||
- `trystero_server.start` / `trystero_server.stop` — spans.
|
||||
- `trystero_server.connections_total{mode,outcome}` — counter.
|
||||
- `trystero_server.messages_relayed_total{mode,outcome}` — counter.
|
||||
- `trystero_server.active_connections{mode}` — up-down gauge.
|
||||
- `trystero_server.start_duration_ms{mode}` — histogram.
|
||||
|
||||
See [`src/otel/otel.md`](./src/otel/otel.md).
|
||||
|
||||
## Companion package
|
||||
|
||||
[`@suaveplan/network-discovery-trystero`](../network-discovery-trystero) is
|
||||
the browser-tier client this daemon serves.
|
||||
Reference in New Issue
Block a user