@rstreamlabs/tunnels 1.0.8 → 1.0.10

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
- Data-plane 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
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,59 +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 `projects` or `workspaces`. Scope-only
69
- requests require a `projectId` or `workspaceId` option and are converted to
70
- targeted grants.
70
+ ## Tunnel and Client Inventory
71
71
 
72
72
  ```ts
73
- import { RstreamTunnelsClient } from "@rstreamlabs/tunnels";
74
-
75
- const admin = new RstreamTunnelsClient({
76
- credentials: {
77
- clientId: process.env.RSTREAM_CLIENT_ID!,
78
- clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
73
+ const tunnels = await client.tunnels.list({
74
+ filters: {
75
+ labels: {
76
+ env: "prod",
77
+ },
79
78
  },
80
- projectEndpoint: "project-endpoint",
81
79
  });
82
80
 
83
- 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({
84
125
  expires_in: 60,
85
- tunnelsGrants: [
86
- {
87
- projects: ["project-id"],
88
- scopes: {
89
- tunnels: {
90
- create: { filters: { protocol: { oneof: ["http"] } } },
91
- connect: { params: { path: { regex: "^/api" } } },
92
- list: { select: { id: true, name: true, protocol: true } },
93
- },
126
+ tunnelsGrants: {
127
+ scopes: {
128
+ tunnels: {
129
+ list: { select: { id: true, name: true, protocol: true } },
130
+ connect: { params: { path: { regex: "^/api" } } },
94
131
  },
95
132
  },
96
- ],
133
+ },
97
134
  });
98
135
  ```
99
136
 
100
- ## 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.
140
+
141
+ ## TURN Credentials
101
142
 
102
- `@rstreamlabs/tunnels` supports the same three TURN credential paths as the
103
- platform:
143
+ The package supports the same TURN credential paths as the platform:
104
144
 
105
145
  - managed API issuance with a short-lived auth token
106
- - local derivation from a PAT
107
- - local derivation from an app `clientId` and `clientSecret`
146
+ - local derivation from a personal access token
147
+ - local derivation from application credentials
108
148
 
109
149
  ```ts
110
150
  import { createTURNCredentials } from "@rstreamlabs/tunnels";
111
151
 
112
152
  const turn = await createTURNCredentials({
113
- credentials: { token: process.env.RSTREAM_AUTHENTICATION_TOKEN! },
153
+ credentials: {
154
+ clientId: process.env.RSTREAM_CLIENT_ID!,
155
+ clientSecret: process.env.RSTREAM_CLIENT_SECRET!,
156
+ },
114
157
  projectEndpoint: "project-endpoint",
158
+ clusterDomain: "cluster.example.rstream.test",
115
159
  });
116
160
  ```
117
161
 
118
- `@rstreamlabs/tunnels` reads `RSTREAM_API_URL`, `RSTREAM_ENGINE`, and
119
- `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
120
178
 
121
- For managed control-plane APIs, 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
+ ```
@@ -67,8 +67,7 @@ var tunnelSchema = z2.object({
67
67
  tls_alpns: z2.array(z2.string()).optional(),
68
68
  tls_min_version: z2.string().optional(),
69
69
  tls_ciphers: z2.array(z2.string()).optional(),
70
- mtls: z2.boolean().optional(),
71
- mtls_ca_cert_pem: z2.string().optional(),
70
+ mtls_auth: z2.boolean().optional(),
72
71
  http_version: z2.enum(["http/1.1", "h2", "h2c", "h3"]).optional(),
73
72
  http_use_tls: z2.boolean().optional(),
74
73
  upstream_tls: z2.boolean().optional(),
@@ -245,7 +244,7 @@ var routedTunnelSchema = z3.object({
245
244
  httpUseTls: z3.boolean().optional(),
246
245
  upstreamTls: z3.boolean().optional(),
247
246
  tokenAuth: z3.boolean().optional(),
248
- mtls: z3.boolean().optional()
247
+ mtls_auth: z3.boolean().optional()
249
248
  });
250
249
  var routingSchema = z3.discriminatedUnion("decision", [
251
250
  z3.object({ decision: z3.literal("routed"), tunnel: routedTunnelSchema }),
@@ -487,7 +486,7 @@ var engineOpenApiDocument = {
487
486
  info: {
488
487
  title: "rstream Engine API",
489
488
  version: "1.0.0",
490
- description: "Operational data-plane 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."
491
490
  },
492
491
  servers: [
493
492
  {