@rstreamlabs/tunnels 3.8.3 → 3.9.0

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
@@ -84,7 +84,9 @@ __export(index_exports, {
84
84
  resolveTunnelsCredentials: () => resolveTunnelsCredentials,
85
85
  resolveTunnelsEngine: () => resolveTunnelsEngine,
86
86
  resolveTunnelsRegion: () => resolveTunnelsRegion,
87
+ resolveWebTTYBrowserEndpoint: () => resolveWebTTYBrowserEndpoint,
87
88
  resolveWebTTYControlRequestParamsSchema: () => resolveWebTTYControlRequestParamsSchema,
89
+ resolveWebTTYServerTransport: () => resolveWebTTYServerTransport,
88
90
  signWebhookPayload: () => signWebhookPayload,
89
91
  streamEndpointSchema: () => streamEndpointSchema,
90
92
  streamEntrySchema: () => streamEntrySchema,
@@ -114,6 +116,7 @@ __export(index_exports, {
114
116
  webTTYTransportSchema: () => webTTYTransportSchema,
115
117
  webhookEventsSchema: () => webhookEventsSchema,
116
118
  webttyServerSchema: () => webttyServerSchema,
119
+ webttyTransportSchema: () => webttyTransportSchema,
117
120
  wsEventsSchema: () => wsEventsSchema
118
121
  });
119
122
  module.exports = __toCommonJS(index_exports);
@@ -2848,6 +2851,11 @@ var webttyEncryptionPolicySchema = z9.enum([
2848
2851
  "explicit_key",
2849
2852
  "workspace_managed"
2850
2853
  ]);
2854
+ var webttyTransportSchema = z9.enum([
2855
+ "plain",
2856
+ "websocket",
2857
+ "webtransport"
2858
+ ]);
2851
2859
  var webttyServerSchema = z9.object({
2852
2860
  tunnel_id: z9.string(),
2853
2861
  tunnel_name: z9.string().optional(),
@@ -2857,7 +2865,11 @@ var webttyServerSchema = z9.object({
2857
2865
  publish: z9.boolean().optional(),
2858
2866
  workspace_id: z9.string().optional(),
2859
2867
  project_id: z9.string().optional(),
2860
- tunnel_protocol: z9.enum(["http", "webtty"]),
2868
+ tunnel_protocol: z9.enum(["http", "webtty"]).optional(),
2869
+ tunnel_type: z9.enum(["bytestream", "datagram"]).optional(),
2870
+ http_version: z9.string().optional(),
2871
+ transport: webttyTransportSchema.optional(),
2872
+ transport_error: z9.string().optional(),
2861
2873
  managed: z9.boolean(),
2862
2874
  host: z9.string(),
2863
2875
  token_auth: z9.boolean(),
@@ -2871,6 +2883,7 @@ var webttyServerSchema = z9.object({
2871
2883
  exec_path: z9.string().optional(),
2872
2884
  fs_path: z9.string().optional(),
2873
2885
  fs_mode: webttyFSModeSchema.optional(),
2886
+ fs_backend: z9.enum(["webdav", "webrtc"]).optional(),
2874
2887
  os_family: osFamilySchema.optional(),
2875
2888
  arch: z9.string().optional(),
2876
2889
  os_id: z9.string().optional(),
@@ -2897,11 +2910,12 @@ function webTTYCapabilitiesForLabels(labels) {
2897
2910
  function webTTYHasCapability(capabilities, capability) {
2898
2911
  return capabilities.includes(capability);
2899
2912
  }
2900
- function parser(tunnel) {
2913
+ function parser(tunnel, includePrivate) {
2901
2914
  if (tunnel.status !== "online") return null;
2902
- if (tunnel.publish !== true) return null;
2915
+ if (tunnel.publish !== true && !includePrivate) return null;
2903
2916
  const managedProtocol = tunnel.protocol === "webtty";
2904
- if (tunnel.protocol !== "http" && !managedProtocol) return null;
2917
+ if (tunnel.protocol !== void 0 && tunnel.protocol !== "http" && !managedProtocol)
2918
+ return null;
2905
2919
  const tunnelLabels = tunnel.labels ?? {};
2906
2920
  if (!managedProtocol && tunnelLabels["application-protocol"] !== "rstream.webtty") {
2907
2921
  return null;
@@ -2929,8 +2943,11 @@ function parser(tunnel) {
2929
2943
  workspace_id: tunnel.workspace_id,
2930
2944
  project_id: tunnel.project_id,
2931
2945
  tunnel_protocol: tunnel.protocol,
2946
+ tunnel_type: tunnel.type,
2947
+ http_version: tunnel.http_version,
2948
+ ...webTTYTransportMetadata(tunnelLabels["rstream.webtty.transport"]),
2932
2949
  managed: managedProtocol,
2933
- host: formatTunnelHost(tunnel),
2950
+ host: formatTunnelHost(tunnel) ?? "",
2934
2951
  token_auth: tunnel.token_auth === true,
2935
2952
  server_id: serverId || void 0,
2936
2953
  server_name: serverName || void 0,
@@ -2941,6 +2958,7 @@ function parser(tunnel) {
2941
2958
  capabilities,
2942
2959
  exec_path: webTTYHasCapability(capabilities, "exec") ? tunnelLabels["rstream.webtty.exec.path"] ?? "/" : void 0,
2943
2960
  fs_path: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.path"] ?? "/fs" : void 0,
2961
+ fs_backend: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.backend"] ?? "webdav" : void 0,
2944
2962
  fs_mode: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.mode"] ?? "read-write" : void 0,
2945
2963
  os_family: tunnelLabels["rstream.webtty.os_family"],
2946
2964
  arch: tunnelLabels["rstream.webtty.arch"],
@@ -2956,8 +2974,54 @@ function parser(tunnel) {
2956
2974
  if (!parsed.success) return null;
2957
2975
  return parsed.data;
2958
2976
  }
2959
- function parseWebTTYServers(tunnels) {
2960
- return tunnels.map((tunnel) => parser(tunnel)).filter((server) => server !== null);
2977
+ function parseWebTTYServers(tunnels, options = {}) {
2978
+ return tunnels.map((tunnel) => parser(tunnel, options.includePrivate === true)).filter((server) => server !== null);
2979
+ }
2980
+ function webTTYTransportMetadata(value) {
2981
+ if (value === void 0) return {};
2982
+ const parsed = webttyTransportSchema.safeParse(value);
2983
+ if (!parsed.success)
2984
+ return {
2985
+ transport_error: "Server advertises an invalid WebTTY transport."
2986
+ };
2987
+ return { transport: parsed.data };
2988
+ }
2989
+ function resolveWebTTYServerTransport(server, requested) {
2990
+ if (server.transport_error !== void 0)
2991
+ throw new Error(server.transport_error);
2992
+ const advertised = server.transport ?? (server.tunnel_type === "datagram" ? "webtransport" : void 0);
2993
+ if (advertised !== void 0 && server.tunnel_type !== void 0 && advertised === "webtransport" !== (server.tunnel_type === "datagram")) {
2994
+ throw new Error(
2995
+ `Server WebTTY transport ${advertised} conflicts with tunnel type ${server.tunnel_type}.`
2996
+ );
2997
+ }
2998
+ if (advertised === "webtransport" && server.http_version !== void 0 && server.http_version !== "h3") {
2999
+ throw new Error("Server WebTransport requires HTTP/3.");
3000
+ }
3001
+ if (requested !== void 0 && advertised !== void 0 && requested !== advertised) {
3002
+ throw new Error(
3003
+ `Requested WebTTY transport ${requested} conflicts with server transport ${advertised}.`
3004
+ );
3005
+ }
3006
+ return advertised ?? requested ?? "websocket";
3007
+ }
3008
+ function resolveWebTTYBrowserEndpoint(server) {
3009
+ const transport = resolveWebTTYServerTransport(server);
3010
+ if (transport === "plain")
3011
+ throw new Error(
3012
+ "Plain WebTTY requires a native client; this server cannot be opened in a browser."
3013
+ );
3014
+ if (server.publish === false || server.host === "")
3015
+ throw new Error(
3016
+ "Private WebTTY requires a native client and its rstrm:// address."
3017
+ );
3018
+ const url = new URL(
3019
+ `${transport === "webtransport" ? "https" : "wss"}://${server.host}`
3020
+ );
3021
+ const execPath = server.exec_path?.trim();
3022
+ if (execPath)
3023
+ url.pathname = execPath.startsWith("/") ? execPath : `/${execPath}`;
3024
+ return { url: url.toString(), transport };
2961
3025
  }
2962
3026
  // Annotate the CommonJS export names for ESM import in node:
2963
3027
  0 && (module.exports = {
@@ -3015,7 +3079,9 @@ function parseWebTTYServers(tunnels) {
3015
3079
  resolveTunnelsCredentials,
3016
3080
  resolveTunnelsEngine,
3017
3081
  resolveTunnelsRegion,
3082
+ resolveWebTTYBrowserEndpoint,
3018
3083
  resolveWebTTYControlRequestParamsSchema,
3084
+ resolveWebTTYServerTransport,
3019
3085
  signWebhookPayload,
3020
3086
  streamEndpointSchema,
3021
3087
  streamEntrySchema,
@@ -3045,5 +3111,6 @@ function parseWebTTYServers(tunnels) {
3045
3111
  webTTYTransportSchema,
3046
3112
  webhookEventsSchema,
3047
3113
  webttyServerSchema,
3114
+ webttyTransportSchema,
3048
3115
  wsEventsSchema
3049
3116
  });
package/dist/index.mjs CHANGED
@@ -1485,6 +1485,11 @@ var webttyEncryptionPolicySchema = z2.enum([
1485
1485
  "explicit_key",
1486
1486
  "workspace_managed"
1487
1487
  ]);
1488
+ var webttyTransportSchema = z2.enum([
1489
+ "plain",
1490
+ "websocket",
1491
+ "webtransport"
1492
+ ]);
1488
1493
  var webttyServerSchema = z2.object({
1489
1494
  tunnel_id: z2.string(),
1490
1495
  tunnel_name: z2.string().optional(),
@@ -1494,7 +1499,11 @@ var webttyServerSchema = z2.object({
1494
1499
  publish: z2.boolean().optional(),
1495
1500
  workspace_id: z2.string().optional(),
1496
1501
  project_id: z2.string().optional(),
1497
- tunnel_protocol: z2.enum(["http", "webtty"]),
1502
+ tunnel_protocol: z2.enum(["http", "webtty"]).optional(),
1503
+ tunnel_type: z2.enum(["bytestream", "datagram"]).optional(),
1504
+ http_version: z2.string().optional(),
1505
+ transport: webttyTransportSchema.optional(),
1506
+ transport_error: z2.string().optional(),
1498
1507
  managed: z2.boolean(),
1499
1508
  host: z2.string(),
1500
1509
  token_auth: z2.boolean(),
@@ -1508,6 +1517,7 @@ var webttyServerSchema = z2.object({
1508
1517
  exec_path: z2.string().optional(),
1509
1518
  fs_path: z2.string().optional(),
1510
1519
  fs_mode: webttyFSModeSchema.optional(),
1520
+ fs_backend: z2.enum(["webdav", "webrtc"]).optional(),
1511
1521
  os_family: osFamilySchema.optional(),
1512
1522
  arch: z2.string().optional(),
1513
1523
  os_id: z2.string().optional(),
@@ -1534,11 +1544,12 @@ function webTTYCapabilitiesForLabels(labels) {
1534
1544
  function webTTYHasCapability(capabilities, capability) {
1535
1545
  return capabilities.includes(capability);
1536
1546
  }
1537
- function parser(tunnel) {
1547
+ function parser(tunnel, includePrivate) {
1538
1548
  if (tunnel.status !== "online") return null;
1539
- if (tunnel.publish !== true) return null;
1549
+ if (tunnel.publish !== true && !includePrivate) return null;
1540
1550
  const managedProtocol = tunnel.protocol === "webtty";
1541
- if (tunnel.protocol !== "http" && !managedProtocol) return null;
1551
+ if (tunnel.protocol !== void 0 && tunnel.protocol !== "http" && !managedProtocol)
1552
+ return null;
1542
1553
  const tunnelLabels = tunnel.labels ?? {};
1543
1554
  if (!managedProtocol && tunnelLabels["application-protocol"] !== "rstream.webtty") {
1544
1555
  return null;
@@ -1566,8 +1577,11 @@ function parser(tunnel) {
1566
1577
  workspace_id: tunnel.workspace_id,
1567
1578
  project_id: tunnel.project_id,
1568
1579
  tunnel_protocol: tunnel.protocol,
1580
+ tunnel_type: tunnel.type,
1581
+ http_version: tunnel.http_version,
1582
+ ...webTTYTransportMetadata(tunnelLabels["rstream.webtty.transport"]),
1569
1583
  managed: managedProtocol,
1570
- host: formatTunnelHost(tunnel),
1584
+ host: formatTunnelHost(tunnel) ?? "",
1571
1585
  token_auth: tunnel.token_auth === true,
1572
1586
  server_id: serverId || void 0,
1573
1587
  server_name: serverName || void 0,
@@ -1578,6 +1592,7 @@ function parser(tunnel) {
1578
1592
  capabilities,
1579
1593
  exec_path: webTTYHasCapability(capabilities, "exec") ? tunnelLabels["rstream.webtty.exec.path"] ?? "/" : void 0,
1580
1594
  fs_path: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.path"] ?? "/fs" : void 0,
1595
+ fs_backend: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.backend"] ?? "webdav" : void 0,
1581
1596
  fs_mode: webTTYHasCapability(capabilities, "fs") ? tunnelLabels["rstream.webtty.fs.mode"] ?? "read-write" : void 0,
1582
1597
  os_family: tunnelLabels["rstream.webtty.os_family"],
1583
1598
  arch: tunnelLabels["rstream.webtty.arch"],
@@ -1593,8 +1608,54 @@ function parser(tunnel) {
1593
1608
  if (!parsed.success) return null;
1594
1609
  return parsed.data;
1595
1610
  }
1596
- function parseWebTTYServers(tunnels) {
1597
- return tunnels.map((tunnel) => parser(tunnel)).filter((server) => server !== null);
1611
+ function parseWebTTYServers(tunnels, options = {}) {
1612
+ return tunnels.map((tunnel) => parser(tunnel, options.includePrivate === true)).filter((server) => server !== null);
1613
+ }
1614
+ function webTTYTransportMetadata(value) {
1615
+ if (value === void 0) return {};
1616
+ const parsed = webttyTransportSchema.safeParse(value);
1617
+ if (!parsed.success)
1618
+ return {
1619
+ transport_error: "Server advertises an invalid WebTTY transport."
1620
+ };
1621
+ return { transport: parsed.data };
1622
+ }
1623
+ function resolveWebTTYServerTransport(server, requested) {
1624
+ if (server.transport_error !== void 0)
1625
+ throw new Error(server.transport_error);
1626
+ const advertised = server.transport ?? (server.tunnel_type === "datagram" ? "webtransport" : void 0);
1627
+ if (advertised !== void 0 && server.tunnel_type !== void 0 && advertised === "webtransport" !== (server.tunnel_type === "datagram")) {
1628
+ throw new Error(
1629
+ `Server WebTTY transport ${advertised} conflicts with tunnel type ${server.tunnel_type}.`
1630
+ );
1631
+ }
1632
+ if (advertised === "webtransport" && server.http_version !== void 0 && server.http_version !== "h3") {
1633
+ throw new Error("Server WebTransport requires HTTP/3.");
1634
+ }
1635
+ if (requested !== void 0 && advertised !== void 0 && requested !== advertised) {
1636
+ throw new Error(
1637
+ `Requested WebTTY transport ${requested} conflicts with server transport ${advertised}.`
1638
+ );
1639
+ }
1640
+ return advertised ?? requested ?? "websocket";
1641
+ }
1642
+ function resolveWebTTYBrowserEndpoint(server) {
1643
+ const transport = resolveWebTTYServerTransport(server);
1644
+ if (transport === "plain")
1645
+ throw new Error(
1646
+ "Plain WebTTY requires a native client; this server cannot be opened in a browser."
1647
+ );
1648
+ if (server.publish === false || server.host === "")
1649
+ throw new Error(
1650
+ "Private WebTTY requires a native client and its rstrm:// address."
1651
+ );
1652
+ const url = new URL(
1653
+ `${transport === "webtransport" ? "https" : "wss"}://${server.host}`
1654
+ );
1655
+ const execPath = server.exec_path?.trim();
1656
+ if (execPath)
1657
+ url.pathname = execPath.startsWith("/") ? execPath : `/${execPath}`;
1658
+ return { url: url.toString(), transport };
1598
1659
  }
1599
1660
  export {
1600
1661
  RstreamAuthResource,
@@ -1651,7 +1712,9 @@ export {
1651
1712
  resolveTunnelsCredentials,
1652
1713
  resolveTunnelsEngine,
1653
1714
  resolveTunnelsRegion,
1715
+ resolveWebTTYBrowserEndpoint,
1654
1716
  resolveWebTTYControlRequestParamsSchema,
1717
+ resolveWebTTYServerTransport,
1655
1718
  signWebhookPayload,
1656
1719
  streamEndpointSchema,
1657
1720
  streamEntrySchema,
@@ -1681,5 +1744,6 @@ export {
1681
1744
  webTTYTransportSchema,
1682
1745
  webhookEventsSchema,
1683
1746
  webttyServerSchema,
1747
+ webttyTransportSchema,
1684
1748
  wsEventsSchema
1685
1749
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rstreamlabs/tunnels",
3
- "version": "3.8.3",
3
+ "version": "3.9.0",
4
4
  "description": "JS/TS SDK for the rstream Engine API and tunnel runtime APIs.",
5
5
  "author": "@uartnet <hello@rstream.io>",
6
6
  "repository": {
@@ -30,15 +30,15 @@
30
30
  ],
31
31
  "scripts": {
32
32
  "build:watch": "tsup --watch",
33
- "build": "tsup",
34
- "clean": "rm -rf dist",
33
+ "build": "tsc --emitDeclarationOnly --declarationMap false --rootDir src --outDir .generated/types && tsup",
34
+ "clean": "rm -rf dist .generated/types",
35
35
  "lint": "eslint \"./**/*.ts*\"",
36
36
  "pretest": "npm --prefix ../rstream run build && npm run build",
37
37
  "test": "node --test ./test/**/*.test.cjs",
38
38
  "type-check": "tsc --noEmit"
39
39
  },
40
40
  "devDependencies": {
41
- "@turbo/gen": "^2.10.6",
41
+ "@turbo/gen": "^2.10.11",
42
42
  "@types/node": "^26",
43
43
  "eslint": "9.39.5",
44
44
  "eslint-config": "*",