TypeScript SDK
Use @net-mesh/sdk for capability discovery and invocation from Node.js.
@net-mesh/core supplies the lower-level event-bus surface.
npm install @net-mesh/sdk @net-mesh/coreChoose the entry point
NetNodeis the event bus. UseemitandsubscribeTyped.MeshNodeprovides capabilities, tools, and nRPC.
Node.js finalizers are not deterministic. Always await node.shutdown() and call
handle.close() on RPC handles so streams and native resources drain explicitly.
Follow the capability path
Protected services
Both authority surfaces live in @net-mesh/core, and the organization half is also
exposed through the @net-mesh/sdk/org facade (OrgClient, serveOrgStreaming,
classifyOrgError). The provider verbs are serveOrgTyped /
serveOrgStreamingTyped / serveOrgClientStreamTyped / serveOrgDuplexTyped in
@net-mesh/core/org, with the @net-mesh/sdk/org wrappers serveOrg /
serveOrgStreaming / serveOrgClientStream / serveOrgDuplex on top; the caller
binds with TypedOrgClient (or the facade's OrgClient) and calls call /
callStreaming / callClientStream / callDuplex
(concepts). The subnet authority plane
(concepts) —
mesh.serveSubnetExported(service, exportName, handler) for a provider
inside a protected subnet, org.callExported(service, req) for the caller, and
subnet.admin.* for runtime gateway administration. Named exports and trust
anchors are configured on the mesh constructor (subnetExports,
subnetAuthorities, …) and validated before the node exists. subnet:<kind>
failures classify through classifySubnetError
(reference).
The rest of the surface
Everything below imports from @net-mesh/sdk, with no reach into
@net-mesh/core:
- Trust:
ConsentPolicy/PinStore/CapabilityGatewayfor consent;DelegationChain,RevocationRegistryandderiveChildIdentityfor delegation;OperatorEnrollment,InviteTokenandDeviceEnrollmentfor enrolling devices, withmesh.serveEnrollmentAuto,mesh.joinandmesh.renewdoing it over the mesh. These take the native identity: passidentity.toNapi(). - Blobs:
createMeshBlobAdapter(redex, id)builds the adapter thatmesh.serveBlobTransferandstoreDirtake.fetchDir(sourceId, manifest, dest)takes none, but the fetching node must have calledserveBlobTransferfirst: it needs the transfer engine too. - Agent tasks and tools:
mesh.serveA2a/submitTask/taskStatus/cancelTask, andmesh.publishTools(needspermissiveChannels: true). - NAT traversal:
mesh.natType(),reflexAddr(),connectDirect,traversalStats()and reflex overrides. - Aggregators:
createRegistryClient(mesh)/createFoldQueryClient(mesh). - Read-your-writes:
tasks.waitForToken(new WriteToken(origin, seq), ms). - Replicated logs:
redex.enableReplication(mesh), thenopenFile(name, { replication: { factor: 3 } })on every node that should take part; the nodes pick the replicas and elect a leader (reference).
node.shutdown() needs the node's only reference. A mesh.rpc() handle, an
aggregator client or a replicating Redex holds one, so release it first
(rpc.raw.close(), client.close(), await redex.disableReplication()), or
shutdown rejects with outstanding references exist.
Serving browser games from Node
A dedicated game host, a world region host or a netcode host can run in Node and
serve pages running @net-mesh/browser:
meshStoreTransport(mesh, { listen })satisfies the browser package's store transport over aMeshNode, sohostStore/joinStore,hostNetcodeand the world helpers run natively.listennames the labels a host must hear before anyone writes (store/<definition id>, a netcode label). It also hasannounce(tags)(replaces this node's tags) andquery(tag), which lists the nodes that announced a tag, in the browser node's descriptor shape.persistStore(host, { file })/restoreStore(file, definition)snapshot a hosted store's document to a RedEX file (only when it changed, and onclose()), and restore the newest snapshot that matches the definition's id and version and passes its validator.mesh.onStreamData(streamId, handler)delivers every event on a stream withpeerNodeId: the peer whose session authenticated it, whichrecvcannot tell you. One subscription per stream id;close()hands the stream back torecv.streamIdFromLabel(label)is the stream id a label names, the same derivation the browser package uses, so a native node and a page that agree on a label open the same stream.StreamConfig.lossyrides the lossy carrier: a fire-and-forget stream's packets travel on a browser session's unordered, zero-retransmit DataChannel. It is refused withreliability: 'reliable'.
The concepts match the other SDKs, while method names, lifecycle, and error shapes follow TypeScript and Node.js conventions.