@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/README.md +1 -1
- package/dist/index.d.mts +2833 -78
- package/dist/index.d.ts +2833 -78
- package/dist/index.js +203 -56
- package/dist/index.mjs +194 -52
- package/package.json +8 -8
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
188
|
-
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
|
223
|
-
|
|
234
|
+
var authTokenScopesSchema = z3.object({
|
|
235
|
+
tunnels: authTokenTunnelsScopesSchema.optional()
|
|
236
|
+
// Scopes related to tunnels
|
|
224
237
|
});
|
|
225
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
498
|
-
const payload =
|
|
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
|
-
|
|
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
|
-
|
|
551
|
-
|
|
696
|
+
createAuthTokenParamsSchema,
|
|
697
|
+
createAuthTokenResponseSchema,
|
|
552
698
|
eventSchema,
|
|
553
699
|
listClientsParamsSchema,
|
|
554
700
|
listClientsResponseSchema,
|
|
555
701
|
listTunnelsParamsSchema,
|
|
556
702
|
listTunnelsResponseSchema,
|
|
557
|
-
|
|
558
|
-
tunnelSchema
|
|
703
|
+
parseWebTTYServers,
|
|
704
|
+
tunnelSchema,
|
|
705
|
+
webttyServerSchema
|
|
559
706
|
});
|