@rstreamlabs/tunnels
v3.1.0
Published
JS/TS SDK for the rstream Engine API and tunnel runtime APIs.
Readme
@rstreamlabs/tunnels
Engine HTTP API SDK for rstream tunnels.
Use this package when code needs operational tunnel state rather than the runtime tunnel protocol itself: list clients and tunnels, watch engine events, validate webhooks, mint scoped tunnel tokens, derive TURN credentials, and work with WebTTY tunnel metadata.
For hosted Control plane operations, use
@rstreamlabs/rstream. For creating and serving
bytestream tunnels from Node.js, use
@rstreamlabs/runtime.
Install
npm install @rstreamlabs/tunnelsClient Setup
Connect directly to a known engine, which is the common self-hosted shape:
import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
const client = new RstreamTunnelsClient({
credentials: { token: process.env.RSTREAM_AUTHENTICATION_TOKEN! },
engine: process.env.RSTREAM_ENGINE!,
});
const tunnels = await client.tunnels.list();
const clients = await client.clients.list();For hosted projects, provide projectEndpoint and let the SDK resolve the
engine through the Control plane API:
import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
const client = new RstreamTunnelsClient({
credentials: { token: process.env.RSTREAM_AUTHENTICATION_TOKEN! },
projectEndpoint: "project-endpoint",
});
const engine = await client.getEngine();
const tunnels = await client.tunnels.list();Application credentials are supported for backend integrations that should mint short-lived engine tokens on demand:
const client = new RstreamTunnelsClient({
credentials: {
clientId: process.env.RSTREAM_CLIENT_ID!,
clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
},
projectEndpoint: "project-endpoint",
});
const tunnels = await client.tunnels.list();When application credentials are used with an explicit engine, also provide
projectId or workspaceId so locally signed engine tokens are scoped.
Tunnel and Client Inventory
const tunnels = await client.tunnels.list({
filters: {
labels: {
env: "prod",
},
},
});
const clients = await client.clients.list();Schemas and TypeScript types are exported for clients, tunnels, stream summaries, and engine events.
Watch Streams
Watch subscribes to engine events over SSE or WebSocket and validates each
event payload.
import { Watch } from "@rstreamlabs/tunnels";
const watch = new Watch(
{
auth: process.env.RSTREAM_AUTHENTICATION_TOKEN!,
engine: process.env.RSTREAM_ENGINE!,
transport: "sse",
},
{
onEvent: (event) => {
console.log(event.type);
},
onClose: () => {
console.log("watch closed");
},
},
);
await watch.connect();URL-based watch authentication requires a short-lived token with bounded lifetime and watch-only tunnel list resources.
Browser integrations should provide auth as a function that calls a backend
token route and returns a fresh watch token for each connection attempt. Do not
store the rstream.token query token as durable browser state.
Scoped Auth Tokens
auth.createAuthToken() mints short-lived engine tokens. Prefer
resources.tunnels when delegating capabilities to devices, browser sessions,
or other services.
const { token } = await client.auth.createAuthToken({
expires_in: 60,
resources: {
tunnels: {
scopes: {
tunnels: {
list: { select: { id: true, name: true, protocol: true } },
connect: { params: { path: { regex: "^/api" } } },
},
},
},
},
});When the client is configured with projectEndpoint or projectId, scope-only
tunnel resources are project-scoped by default. Pass projectScoped: false
only when a global scope-only tunnel resource is intentional.
TURN Credentials
The package supports the same TURN credential paths as the platform:
- managed API issuance with a short-lived auth token
- local derivation from a personal access token
- local derivation from application credentials
import { createTURNCredentials } from "@rstreamlabs/tunnels";
const turn = await createTURNCredentials({
credentials: {
clientId: process.env.RSTREAM_CLIENT_ID!,
clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
},
projectEndpoint: "project-endpoint",
clusterDomain: "cluster.example.rstream.test",
ttlSeconds: 600,
});TURN credentials are short-lived. ttlSeconds is optional, defaults to 600 for
local derivation, and must be an integer between 1 and 3600 seconds. PAT-backed
credentials are additionally capped by the PAT expiration.
Webhooks
Validate signed engine webhook payloads with constant-time signature comparison and schema parsing:
const event = await client.webhooks.event(
rawBody,
request.headers.get("rstream-signature")!,
process.env.WEBHOOK_SECRET!,
);
console.log(event.type);WebTTY Helpers
Use parseWebTTYServers() to derive WebTTY server metadata from tunnel
inventory.
import { parseWebTTYServers } from "@rstreamlabs/tunnels";
const servers = parseWebTTYServers(await client.tunnels.list());WebTTY server metadata includes advertised capabilities such as exec and
fs. Older servers that do not advertise capabilities are treated as
exec-only with the execution path /.
OpenAPI Document
The package exports the Engine API OpenAPI document from the main entrypoint
and from the @rstreamlabs/tunnels/openapi subpath.
import { engineOpenApiDocument } from "@rstreamlabs/tunnels/openapi";
console.log(engineOpenApiDocument.info.title);Environment Variables
| Variable | Purpose |
| ------------------------------ | --------------------------------------------------------------- |
| RSTREAM_API_URL | Control plane API URL used for managed project resolution. |
| RSTREAM_ENGINE | Engine endpoint used when no engine is provided explicitly. |
| RSTREAM_AUTHENTICATION_TOKEN | Bearer token used when credentials are not provided explicitly. |
Development
npm --workspace @rstreamlabs/tunnels run test
npm --workspace @rstreamlabs/tunnels run type-check
npm --workspace @rstreamlabs/tunnels run lint
npm --workspace @rstreamlabs/tunnels run build