@rstreamlabs/tunnels 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,18 +1,26 @@
1
1
  # `@rstreamlabs/tunnels`
2
2
 
3
- Engine API JS/TS SDK for rstream tunnels.
3
+ Engine HTTP API SDK for rstream tunnels.
4
4
 
5
- Use this package to talk directly to the tunnels engine: list tunnels, inspect
6
- clients, watch engine events, validate webhooks, and create fine-grained app
7
- tokens.
5
+ Use this package when code needs operational tunnel state rather than the
6
+ runtime tunnel protocol itself: list clients and tunnels, watch engine events,
7
+ validate webhooks, mint scoped tunnel tokens, derive TURN credentials, and work
8
+ with WebTTY tunnel metadata.
8
9
 
9
- The package supports both:
10
+ For hosted Control plane operations, use
11
+ [`@rstreamlabs/rstream`](../rstream/README.md). For creating and serving
12
+ bytestream tunnels from Node.js, use
13
+ [`@rstreamlabs/runtime`](../runtime/README.md).
10
14
 
11
- - direct engine usage, including self-hosted deployments
12
- - managed rstream projects resolved via the Control plane API
13
- - bearer-token authentication and application credentials
15
+ ## Install
14
16
 
15
- ## Self-hosted usage
17
+ ```sh
18
+ npm install @rstreamlabs/tunnels
19
+ ```
20
+
21
+ ## Client Setup
22
+
23
+ Connect directly to a known engine, which is the common self-hosted shape:
16
24
 
17
25
  ```ts
18
26
  import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
@@ -23,9 +31,11 @@ const client = new RstreamTunnelsClient({
23
31
  });
24
32
 
25
33
  const tunnels = await client.tunnels.list();
34
+ const clients = await client.clients.list();
26
35
  ```
27
36
 
28
- ## Managed usage
37
+ For hosted projects, provide `projectEndpoint` and let the SDK resolve the
38
+ engine through the Control plane API:
29
39
 
30
40
  ```ts
31
41
  import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
@@ -36,22 +46,13 @@ const client = new RstreamTunnelsClient({
36
46
  });
37
47
 
38
48
  const engine = await client.getEngine();
39
- const turn = await client.turn.createCredentials();
49
+ const tunnels = await client.tunnels.list();
40
50
  ```
41
51
 
42
- ## Application Credentials
43
-
44
- `@rstreamlabs/tunnels` can work directly with an app `clientId` and
45
- `clientSecret`. This is the intended backend flow when you want the server to
46
- mint short-lived tokens for downstream clients.
47
-
48
- Managed `projectEndpoint` clients mint engine tokens restricted to the resolved
49
- project. Explicit `engine` clients using application credentials must provide
50
- `projectId` or `workspaceId` so locally signed engine tokens are not global.
52
+ Application credentials are supported for backend integrations that should mint
53
+ short-lived engine tokens on demand:
51
54
 
52
55
  ```ts
53
- import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
54
-
55
56
  const client = new RstreamTunnelsClient({
56
57
  credentials: {
57
58
  clientId: process.env.RSTREAM_CLIENT_ID!,
@@ -63,58 +64,151 @@ const client = new RstreamTunnelsClient({
63
64
  const tunnels = await client.tunnels.list();
64
65
  ```
65
66
 
66
- ## Fine-Grained Tokens
67
+ When application credentials are used with an explicit `engine`, also provide
68
+ `projectId` or `workspaceId` so locally signed engine tokens are scoped.
67
69
 
68
- Prefer `tunnelsGrants` with explicit operation scopes. When the client is
69
- configured with `projectEndpoint` or `projectId`, scope-only requests and
70
- scope-only grant leaves are project-scoped by default. Pass
71
- `projectScoped: false` only when you intentionally need a global scope-only
72
- grant.
70
+ ## Tunnel and Client Inventory
73
71
 
74
72
  ```ts
75
- import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
76
-
77
- const admin = new RstreamTunnelsClient({
78
- credentials: {
79
- clientId: process.env.RSTREAM_CLIENT_ID!,
80
- clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
73
+ const tunnels = await client.tunnels.list({
74
+ filters: {
75
+ labels: {
76
+ env: "prod",
77
+ },
81
78
  },
82
- projectEndpoint: "project-endpoint",
83
79
  });
84
80
 
85
- const { token } = await admin.auth.createAuthToken({
81
+ const clients = await client.clients.list();
82
+ ```
83
+
84
+ Schemas and TypeScript types are exported for clients, tunnels, stream
85
+ summaries, and engine events.
86
+
87
+ ## Watch Streams
88
+
89
+ `Watch` subscribes to engine events over SSE or WebSocket and validates each
90
+ event payload.
91
+
92
+ ```ts
93
+ import { Watch } from "@rstreamlabs/tunnels";
94
+
95
+ const watch = new Watch(
96
+ {
97
+ auth: process.env.RSTREAM_AUTHENTICATION_TOKEN!,
98
+ engine: process.env.RSTREAM_ENGINE!,
99
+ transport: "sse",
100
+ },
101
+ {
102
+ onEvent: (event) => {
103
+ console.log(event.type);
104
+ },
105
+ onClose: () => {
106
+ console.log("watch closed");
107
+ },
108
+ },
109
+ );
110
+
111
+ await watch.connect();
112
+ ```
113
+
114
+ URL-based watch authentication requires a short-lived token with bounded
115
+ lifetime and watch-only tunnel list grants.
116
+
117
+ ## Scoped Auth Tokens
118
+
119
+ `auth.createAuthToken()` mints short-lived engine tokens. Prefer
120
+ `tunnelsGrants` when delegating capabilities to devices, browser sessions, or
121
+ other services.
122
+
123
+ ```ts
124
+ const { token } = await client.auth.createAuthToken({
86
125
  expires_in: 60,
87
126
  tunnelsGrants: {
88
127
  scopes: {
89
128
  tunnels: {
90
- create: { filters: { protocol: { oneof: ["http"] } } },
91
- connect: { params: { path: { regex: "^/api" } } },
92
129
  list: { select: { id: true, name: true, protocol: true } },
130
+ connect: { params: { path: { regex: "^/api" } } },
93
131
  },
94
132
  },
95
133
  },
96
134
  });
97
135
  ```
98
136
 
99
- ## TURN credentials
137
+ When the client is configured with `projectEndpoint` or `projectId`, scope-only
138
+ requests and scope-only grant leaves are project-scoped by default. Pass
139
+ `projectScoped: false` only when a global scope-only grant is intentional.
100
140
 
101
- `@rstreamlabs/tunnels` supports the same three TURN credential paths as the
102
- platform:
141
+ ## TURN Credentials
142
+
143
+ The package supports the same TURN credential paths as the platform:
103
144
 
104
145
  - managed API issuance with a short-lived auth token
105
- - local derivation from a PAT
106
- - local derivation from an app `clientId` and `clientSecret`
146
+ - local derivation from a personal access token
147
+ - local derivation from application credentials
107
148
 
108
149
  ```ts
109
150
  import { createTURNCredentials } from "@rstreamlabs/tunnels";
110
151
 
111
152
  const turn = await createTURNCredentials({
112
- credentials: { token: process.env.RSTREAM_AUTHENTICATION_TOKEN! },
153
+ credentials: {
154
+ clientId: process.env.RSTREAM_CLIENT_ID!,
155
+ clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
156
+ },
113
157
  projectEndpoint: "project-endpoint",
158
+ clusterDomain: "cluster.example.rstream.test",
114
159
  });
115
160
  ```
116
161
 
117
- `@rstreamlabs/tunnels` reads `RSTREAM_API_URL`, `RSTREAM_ENGINE`, and
118
- `RSTREAM_AUTHENTICATION_TOKEN` when they are not provided explicitly.
162
+ ## Webhooks
163
+
164
+ Validate signed engine webhook payloads with constant-time signature comparison
165
+ and schema parsing:
166
+
167
+ ```ts
168
+ const event = await client.webhooks.event(
169
+ rawBody,
170
+ request.headers.get("rstream-signature")!,
171
+ process.env.WEBHOOK_SECRET!,
172
+ );
173
+
174
+ console.log(event.type);
175
+ ```
176
+
177
+ ## WebTTY Helpers
119
178
 
120
- For the Control plane API, use [`@rstreamlabs/rstream`](../rstream/README.md).
179
+ Use `parseWebTTYServers()` to derive WebTTY server metadata from tunnel
180
+ inventory.
181
+
182
+ ```ts
183
+ import { parseWebTTYServers } from "@rstreamlabs/tunnels";
184
+
185
+ const servers = parseWebTTYServers(await client.tunnels.list());
186
+ ```
187
+
188
+ ## OpenAPI Document
189
+
190
+ The package exports the Engine API OpenAPI document from the main entrypoint
191
+ and from the `@rstreamlabs/tunnels/openapi` subpath.
192
+
193
+ ```ts
194
+ import { engineOpenApiDocument } from "@rstreamlabs/tunnels/openapi";
195
+
196
+ console.log(engineOpenApiDocument.info.title);
197
+ ```
198
+
199
+ ## Environment Variables
200
+
201
+ | Variable | Purpose |
202
+ | --- | --- |
203
+ | `RSTREAM_API_URL` | Control plane API URL used for managed project resolution. |
204
+ | `RSTREAM_ENGINE` | Engine endpoint used when no engine is provided explicitly. |
205
+ | `RSTREAM_AUTHENTICATION_TOKEN` | Bearer token used when credentials are not provided explicitly. |
206
+
207
+ ## Development
208
+
209
+ ```sh
210
+ npm --workspace @rstreamlabs/tunnels run test
211
+ npm --workspace @rstreamlabs/tunnels run type-check
212
+ npm --workspace @rstreamlabs/tunnels run lint
213
+ npm --workspace @rstreamlabs/tunnels run build
214
+ ```
@@ -486,7 +486,7 @@ var engineOpenApiDocument = {
486
486
  info: {
487
487
  title: "rstream Engine API",
488
488
  version: "1.0.0",
489
- description: "Operational Engine API exposed by rstream-engine. This surface is scoped to the authenticated engine or project endpoint and covers live clients, live tunnels, and state-change streams."
489
+ description: "Operational Engine API exposed by rstream engine. This surface is scoped to the authenticated engine or project endpoint and covers live clients, live tunnels, and state-change streams."
490
490
  },
491
491
  servers: [
492
492
  {