@rstreamlabs/rstream 1.4.0 → 1.6.1

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/dist/index.js CHANGED
@@ -37,16 +37,21 @@ __export(index_exports, {
37
37
  RstreamTunnelsRessource: () => RstreamTunnelsRessource,
38
38
  RstreamWebHooksRessource: () => RstreamWebHooksRessource,
39
39
  Watch: () => Watch,
40
+ authTokenPermissionsSchema: () => authTokenPermissionsSchema,
41
+ authTokenSchema: () => authTokenSchema,
42
+ authTokenScopesSchema: () => authTokenScopesSchema,
43
+ authTokenTunnelsScopesSchema: () => authTokenTunnelsScopesSchema,
40
44
  clientSchema: () => clientSchema,
41
- createShortTermTokenParamsSchema: () => createShortTermTokenParamsSchema,
42
- createShortTermTokenResponseSchema: () => createShortTermTokenResponseSchema,
45
+ createAuthTokenParamsSchema: () => createAuthTokenParamsSchema,
46
+ createAuthTokenResponseSchema: () => createAuthTokenResponseSchema,
43
47
  eventSchema: () => eventSchema,
44
48
  listClientsParamsSchema: () => listClientsParamsSchema,
45
49
  listClientsResponseSchema: () => listClientsResponseSchema,
46
50
  listTunnelsParamsSchema: () => listTunnelsParamsSchema,
47
51
  listTunnelsResponseSchema: () => listTunnelsResponseSchema,
48
- rstreamAuthPayloadSchema: () => rstreamAuthPayloadSchema,
49
- tunnelSchema: () => tunnelSchema
52
+ parseWebTTYServers: () => parseWebTTYServers,
53
+ tunnelSchema: () => tunnelSchema,
54
+ webttyServerSchema: () => webttyServerSchema
50
55
  });
51
56
  module.exports = __toCommonJS(index_exports);
52
57
 
@@ -58,11 +63,11 @@ var RstreamAuthRessource = class {
58
63
  constructor(client) {
59
64
  this.client = client;
60
65
  }
61
- async createShortTermToken(params, options) {
66
+ async createAuthToken(params, options) {
62
67
  const credentials = options?.credentials || this.client.credentials;
63
68
  if (!credentials || !("clientId" in credentials)) {
64
69
  throw new Error(
65
- "Application credentials (client id, client secret) are required to create a short term token."
70
+ "Application credentials (client id, client secret) are required to create an auth token."
66
71
  );
67
72
  }
68
73
  const now = Math.floor(Date.now() / 1e3);
@@ -74,9 +79,10 @@ var RstreamAuthRessource = class {
74
79
  // Expiration time
75
80
  type: "app",
76
81
  clientId: credentials.clientId,
82
+ permissions: null,
77
83
  metadata: {
78
84
  engine: this.client.engine,
79
- permissions: params?.permissions
85
+ scopes: params?.scopes
80
86
  }
81
87
  };
82
88
  const pk = import_crypto.default.createPrivateKey({
@@ -143,6 +149,8 @@ var tunnelSchema = z2.object({
143
149
  // common properties
144
150
  client_id: z2.string(),
145
151
  user_id: z2.string(),
152
+ project_id: z2.string(),
153
+ workspace_id: z2.string(),
146
154
  status: z2.enum(["online", "offline"]),
147
155
  // tunnel properties
148
156
  id: z2.string(),
@@ -184,66 +192,89 @@ var listTunnelsResponseSchema = z2.array(tunnelSchema);
184
192
 
185
193
  // src/auth.ts
186
194
  var z3 = __toESM(require("zod"));
187
- var createShortTermTokenParamsSchema = z3.object({
188
- expires_in: z3.number().default(60),
189
- // 1 minute
190
- permissions: z3.object({
191
- // Permissions for creating a tunnel
192
- create: z3.union([
193
- z3.boolean(),
194
- z3.object({
195
- filters: filters(tunnelSchema).optional()
196
- })
197
- ]).optional(),
198
- // Permissions for connecting to a tunnel
199
- connect: z3.union([
200
- z3.boolean(),
201
- z3.object({
202
- filters: filters(tunnelSchema).optional(),
203
- params: filters(
204
- z3.object({
205
- path: z3.string().optional()
206
- })
207
- ).optional()
208
- })
209
- ]).optional(),
210
- // Permissions for listing tunnels
211
- list: z3.union([
212
- z3.boolean(),
213
- z3.object({
214
- filters: filters(tunnelSchema).optional(),
215
- select: select(tunnelSchema).optional()
216
- })
217
- ]).optional()
218
- }),
219
- // Additional metadata
220
- metadata: z3.unknown().optional()
195
+ var authTokenPermissionsSchema = z3.array(z3.string());
196
+ var authTokenTunnelsScopesSchema = z3.object({
197
+ // Scopes for creating tunnels
198
+ create: z3.union([
199
+ z3.boolean(),
200
+ z3.object({
201
+ filters: filters(
202
+ tunnelSchema.omit({
203
+ client_id: true,
204
+ project_id: true,
205
+ workspace_id: true,
206
+ user_id: true,
207
+ status: true,
208
+ creation_date: true
209
+ })
210
+ ).optional()
211
+ })
212
+ ]).optional(),
213
+ // Scopes for connecting to tunnels
214
+ connect: z3.union([
215
+ z3.boolean(),
216
+ z3.object({
217
+ filters: filters(tunnelSchema).optional(),
218
+ params: filters(
219
+ z3.object({
220
+ path: z3.string().optional()
221
+ })
222
+ ).optional()
223
+ })
224
+ ]).optional(),
225
+ // Scopes for listing tunnels
226
+ list: z3.union([
227
+ z3.boolean(),
228
+ z3.object({
229
+ filters: filters(tunnelSchema).optional(),
230
+ select: select(tunnelSchema).optional()
231
+ })
232
+ ]).optional()
221
233
  });
222
- var createShortTermTokenResponseSchema = z3.object({
223
- token: z3.string()
234
+ var authTokenScopesSchema = z3.object({
235
+ tunnels: authTokenTunnelsScopesSchema.optional()
236
+ // Scopes related to tunnels
224
237
  });
225
- var rstreamAuthPayloadSchema = z3.discriminatedUnion("type", [
238
+ var authTokenSchema = z3.union([
239
+ z3.object({
240
+ type: z3.literal("auth"),
241
+ userId: z3.string(),
242
+ permissions: authTokenPermissionsSchema.nullable()
243
+ }),
226
244
  z3.object({
227
245
  type: z3.literal("pat")
228
246
  }),
229
247
  z3.object({
230
248
  type: z3.literal("app"),
231
- clientId: z3.string()
249
+ clientId: z3.string(),
250
+ permissions: authTokenPermissionsSchema.nullable()
232
251
  })
233
252
  ]).and(
234
253
  z3.object({
235
254
  metadata: z3.object({
236
255
  engine: z3.string().optional(),
237
- permissions: createShortTermTokenParamsSchema.shape.permissions.optional()
256
+ scopes: authTokenScopesSchema.optional()
238
257
  }).optional()
239
258
  })
240
259
  );
260
+ var createAuthTokenParamsSchema = z3.object({
261
+ expires_in: z3.number().default(60),
262
+ // 1 minute
263
+ scopes: authTokenScopesSchema.optional(),
264
+ metadata: z3.unknown().optional()
265
+ // Additional metadata
266
+ });
267
+ var createAuthTokenResponseSchema = z3.object({
268
+ token: z3.string()
269
+ });
241
270
 
242
271
  // src/client.ts
243
272
  var z4 = __toESM(require("zod"));
244
273
  var clientSchema = z4.object({
245
274
  id: z4.string(),
246
275
  user_id: z4.string(),
276
+ project_id: z4.string(),
277
+ workspace_id: z4.string(),
247
278
  status: z4.enum(["online", "offline"]),
248
279
  details: z4.object({
249
280
  agent: z4.string().optional(),
@@ -407,7 +438,13 @@ var RstreamClient = class {
407
438
  this.cfg = config;
408
439
  }
409
440
  get engine() {
410
- return this.cfg?.engine || process.env.RSTREAM_DEFAULT_ENGINE || "engine.rstream.io:443";
441
+ if (this.cfg?.engine) {
442
+ return this.cfg.engine;
443
+ }
444
+ if (process.env.RSTREAM_DEFAULT_ENGINE) {
445
+ return process.env.RSTREAM_DEFAULT_ENGINE;
446
+ }
447
+ return void 0;
411
448
  }
412
449
  get credentials() {
413
450
  if (this.cfg?.credentials && "token" in this.cfg.credentials) {
@@ -430,7 +467,13 @@ var RstreamClient = class {
430
467
  return void 0;
431
468
  }
432
469
  get api() {
433
- return `https://${this.engine}/api`;
470
+ const engine = this.engine;
471
+ if (!engine) {
472
+ throw new Error(
473
+ "Engine URL is not defined. Please provide an engine in the rstream client configuration or set the RSTREAM_DEFAULT_ENGINE environment variable."
474
+ );
475
+ }
476
+ return `https://${engine}/api`;
434
477
  }
435
478
  get auth() {
436
479
  return new RstreamAuthRessource(this);
@@ -450,7 +493,7 @@ var RstreamClient = class {
450
493
  return credentials.token;
451
494
  }
452
495
  if (credentials && "clientId" in credentials) {
453
- return (await this.auth.createShortTermToken(void 0, {
496
+ return (await this.auth.createAuthToken(void 0, {
454
497
  credentials: {
455
498
  clientId: credentials.clientId,
456
499
  clientSecret: credentials.clientSecret
@@ -494,11 +537,16 @@ var Watch = class {
494
537
  throw new Error("Watch: Connection already started or closed.");
495
538
  }
496
539
  this.connectionState = "connecting";
497
- const token = await this.config.auth.token();
498
- const payload = rstreamAuthPayloadSchema.parse(
540
+ const token = typeof this.config.auth === "function" ? await this.config.auth() : this.config.auth;
541
+ const payload = authTokenSchema.parse(
499
542
  import_jsonwebtoken2.default.decode(token, { complete: false })
500
543
  );
501
- const base = `https://${this.config.engine || payload.metadata?.engine || "engine.rstream.io:443"}`;
544
+ if (this.config.engine === void 0 && payload.metadata?.engine === void 0) {
545
+ throw new Error(
546
+ "Watch: No engine specified in configuration or token metadata."
547
+ );
548
+ }
549
+ const base = `https://${this.config.engine || payload.metadata?.engine}`;
502
550
  if (this.config.transport === "sse") {
503
551
  const url = new URL(`/api/sse`, base);
504
552
  url.searchParams.set("rstream.token", token);
@@ -522,6 +570,13 @@ var Watch = class {
522
570
  this.disconnect();
523
571
  }
524
572
  };
573
+ if (this.connection instanceof WebSocket) {
574
+ this.connection.onclose = () => {
575
+ if (this.connectionState !== "closed") {
576
+ this.disconnect();
577
+ }
578
+ };
579
+ }
525
580
  }
526
581
  disconnect() {
527
582
  if (this.connection) {
@@ -537,6 +592,93 @@ var Watch = class {
537
592
  }
538
593
  }
539
594
  };
595
+
596
+ // src/webtty.ts
597
+ var z6 = __toESM(require("zod"));
598
+ var osFamilies = [
599
+ "linux",
600
+ "macos",
601
+ "windows",
602
+ "netbsd",
603
+ "openbsd",
604
+ "freebsd"
605
+ ];
606
+ var architectures = [
607
+ "x86_i386",
608
+ "x86_i686",
609
+ "x86_64",
610
+ "x86_64_v2",
611
+ "x86_64_v3",
612
+ "x86_64_v4",
613
+ "armv6",
614
+ "armv6hf",
615
+ "armv7",
616
+ "armv7hf",
617
+ "arm64",
618
+ "mips",
619
+ "mipsle",
620
+ "mips64",
621
+ "mips64le",
622
+ "ppc64",
623
+ "ppc64le",
624
+ "riscv64"
625
+ ];
626
+ var webttyServerSchema = z6.object({
627
+ tunnel_id: z6.string(),
628
+ host: z6.string(),
629
+ token_auth: z6.boolean(),
630
+ os_family: z6.enum(osFamilies).optional(),
631
+ arch: z6.enum(architectures).optional(),
632
+ os_id: z6.string().optional(),
633
+ // /etc/os-release::ID (ubuntu, debian, rocky, etc.)
634
+ os_version_id: z6.string().optional(),
635
+ // /etc/os-release::VERSION_ID (24.04, 22.04, 11, 10.0.19045, ...)
636
+ os_version_codename: z6.string().optional(),
637
+ // /etc/os-release::VERSION_CODENAME (jammy, noble...)
638
+ os_pretty_name: z6.string().optional(),
639
+ // /etc/os-release::PRETTY_NAME
640
+ kernel_release: z6.string().optional(),
641
+ // uname -r
642
+ hostname: z6.string().optional(),
643
+ // uname -n
644
+ labels: z6.record(z6.string(), z6.string().optional()).optional()
645
+ });
646
+ function parser(tunnel) {
647
+ if (tunnel.status !== "online") return null;
648
+ if (tunnel.publish !== true) return null;
649
+ if (tunnel.protocol !== "http") return null;
650
+ const tunnelLabels = tunnel.labels ?? {};
651
+ if (tunnelLabels["application-protocol"] !== "rstream.webtty") {
652
+ return null;
653
+ }
654
+ const labels = {};
655
+ for (const [key, value] of Object.entries(tunnelLabels)) {
656
+ if (!key.startsWith("rstream.webtty.label.")) continue;
657
+ const labelKey = key.slice("rstream.webtty.label.".length);
658
+ if (labelKey.length === 0) continue;
659
+ labels[labelKey] = value;
660
+ }
661
+ const candidate = {
662
+ tunnel_id: tunnel.id,
663
+ host: tunnel.host,
664
+ token_auth: tunnel.token_auth === true,
665
+ os_family: tunnelLabels["rstream.webtty.os_family"],
666
+ arch: tunnelLabels["rstream.webtty.arch"],
667
+ os_id: tunnelLabels["rstream.webtty.os_id"],
668
+ os_version_id: tunnelLabels["rstream.webtty.os_version_id"],
669
+ os_version_codename: tunnelLabels["rstream.webtty.os_version_codename"],
670
+ os_pretty_name: tunnelLabels["rstream.webtty.os_pretty_name"],
671
+ kernel_release: tunnelLabels["rstream.webtty.kernel_release"],
672
+ hostname: tunnelLabels["rstream.webtty.hostname"],
673
+ labels: Object.keys(labels).length > 0 ? labels : void 0
674
+ };
675
+ const parsed = webttyServerSchema.safeParse(candidate);
676
+ if (!parsed.success) return null;
677
+ return parsed.data;
678
+ }
679
+ function parseWebTTYServers(tunnels) {
680
+ return tunnels.map((tunnel) => parser(tunnel)).filter((server) => server !== null);
681
+ }
540
682
  // Annotate the CommonJS export names for ESM import in node:
541
683
  0 && (module.exports = {
542
684
  Rstream,
@@ -546,14 +688,19 @@ var Watch = class {
546
688
  RstreamTunnelsRessource,
547
689
  RstreamWebHooksRessource,
548
690
  Watch,
691
+ authTokenPermissionsSchema,
692
+ authTokenSchema,
693
+ authTokenScopesSchema,
694
+ authTokenTunnelsScopesSchema,
549
695
  clientSchema,
550
- createShortTermTokenParamsSchema,
551
- createShortTermTokenResponseSchema,
696
+ createAuthTokenParamsSchema,
697
+ createAuthTokenResponseSchema,
552
698
  eventSchema,
553
699
  listClientsParamsSchema,
554
700
  listClientsResponseSchema,
555
701
  listTunnelsParamsSchema,
556
702
  listTunnelsResponseSchema,
557
- rstreamAuthPayloadSchema,
558
- tunnelSchema
703
+ parseWebTTYServers,
704
+ tunnelSchema,
705
+ webttyServerSchema
559
706
  });