Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
# @suaveplan/network-libp2p-server - Server-tier libp2p relay daemon (bootstrap + circuit-relay-v2) paired with @suaveplan/network-transport-libp2p — Node-only HTTP/libp2p host with structural Zod option validation, AbortSignal lifecycle, health/ready/live endpoints, OTel observability, and injectable libp2p factory for real-fake integration tests.
## Summary
Server-tier libp2p relay daemon paired with
[`@suaveplan/network-transport-libp2p`](../network-transport-libp2p).
Hosts a libp2p node configured as a bootstrap + circuit-relay-v2 server
alongside an inline HTTP listener exposing `/health`, `/ready`, `/live`
verbs.
<!-- 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 -->
- [health-listener](./src/server/health-listener.md) — Wraps the asynchronous `http.Server.listen(port, host)` flow with the listener-attach / `EADDRINUSE` classification / `…
- [peer-events](./src/server/peer-events.md) — Wires the `peer:connect` and `peer:disconnect` event listeners onto a `Libp2pServerNodeLike` and bridges them onto the…
- [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)_- [health-listener](./src/server/health-listener.md) — Wraps the asynchronous `http.Server.listen(port, host)` flow with the listener-attach / `EADDRINUSE` classification / `…
- [peer-events](./src/server/peer-events.md) — Wires the `peer:connect` and `peer:disconnect` event listeners onto a `Libp2pServerNodeLike` and bridges them onto the…
- [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)_- [health-listener](./src/server/health-listener.md) — Wraps the asynchronous `http.Server.listen(port, host)` flow with the listener-attach / `EADDRINUSE` classification / `…
- [peer-events](./src/server/peer-events.md) — Wires the `peer:connect` and `peer:disconnect` event listeners onto a `Libp2pServerNodeLike` and bridges them onto the…
- [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)_- [health-listener](./src/server/health-listener.md) — Wraps the asynchronous `http.Server.listen(port, host)` flow with the listener-attach / `EADDRINUSE` classification / `…
- [peer-events](./src/server/peer-events.md) — Wires the `peer:connect` and `peer:disconnect` event listeners onto a `Libp2pServerNodeLike` and bridges them onto the…
- [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)_ - [health-listener](./src/server/health-listener.md) — Wraps the asynchronous `http.Server.listen(port, host)` flow with the listener-attach / `EADDRINUSE` classification / `…
- [peer-events](./src/server/peer-events.md) — Wires the `peer:connect` and `peer:disconnect` event listeners onto a `Libp2pServerNodeLike` and bridges them onto the…
- [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)_
## Run the daemon
```ts
import { createLibp2p } from "libp2p";
import { tcp } from "@libp2p/tcp";
import { webSockets } from "@libp2p/websockets";
import { noise } from "@chainsafe/libp2p-noise";
import { yamux } from "@chainsafe/libp2p-yamux";
import { identify } from "@libp2p/identify";
import { circuitRelayServer } from "@libp2p/circuit-relay-v2";
import { bootstrap } from "@libp2p/bootstrap";
import { Libp2pServer } from "@suaveplan/network-libp2p-server";
const server = new Libp2pServer({
listen: ["/ip4/0.0.0.0/tcp/9090", "/ip4/0.0.0.0/tcp/9091/ws"],
bootstrap: ["/dnsaddr/bootstrap.libp2p.io/p2p/QmNnoo..."],
autoRelay: { enabled: true, maxConnections: 500 },
healthPort: 9099,
libp2pFactory: async (cfg) =>
createLibp2p({
addresses: { listen: [...cfg.listen] },
transports: [tcp(), webSockets()],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
peerDiscovery:
cfg.bootstrap.length > 0
? [bootstrap({ list: [...cfg.bootstrap] })]
: [],
services: {
identify: identify(),
relay: circuitRelayServer({
reservations: {
maxReservations: cfg.autoRelay.maxConnections,
},
}),
},
connectionManager: { maxConnections: cfg.maxConnections },
}),
});
const { peerId, multiaddrs } = await server.start();
console.log(`libp2p relay ${peerId} on:`);
for (const a of multiaddrs) console.log(` ${a}`);
// Graceful shutdown
process.on("SIGTERM", () => server.stop());
```
## Test environment
Tests inject a deterministic `FakeLibp2pServerNode` so the native
transitive deps of the real `libp2p` package never enter the test
surface — the daemon never resolves `libp2p` at module evaluation time
and the integration suite boots a real `Libp2pServer` inside the test
process.
```ts
import { Libp2pServer } from "@suaveplan/network-libp2p-server";
import {
FakeLibp2pHub,
makeFakeServerFactory,
} from "./tests/setup/fake-libp2p-server.js";
const hub = new FakeLibp2pHub();
const { factory } = makeFakeServerFactory(hub);
const server = new Libp2pServer({
libp2pFactory: factory,
listen: ["/ip4/0.0.0.0/tcp/0"],
healthPort: 0,
});
await server.start();
// ... drive the daemon, then:
await server.stop();
```
## Acceptance gates
- `bunx turbo lint typecheck test --filter=@suaveplan/network-libp2p-server`
- `bunx turbo test:coverage --filter=@suaveplan/network-libp2p-server` → 100/100/100/100
- `bun run docs:check --filter=@suaveplan/network-libp2p-server`
## API
See per-module `.md` docs:
- [`src/server/server.md`](src/server/server.md) — `Libp2pServer` daemon
- [`src/server/peer-events.md`](src/server/peer-events.md) — peer
connect/disconnect bridging
- [`src/server/health-listener.md`](src/server/health-listener.md) —
inline-HTTP `listenHttp` helper
- [`src/health/health.md`](src/health/health.md) — `/health` / `/ready`
/ `/live` verb pipeline
- [`src/otel/otel.md`](src/otel/otel.md) — OTel instrumentation surface
- [`src/errors/errors.md`](src/errors/errors.md) — error registry
- [`src/types/types.md`](src/types/types.md) — public type contracts