traforo 0.0.8 → 0.0.9

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 CHANGED
@@ -1,24 +1,19 @@
1
- TRAFORO
2
- =======
1
+ # TRAFORO
3
2
 
4
3
  HTTP tunnel via Cloudflare Durable Objects and WebSockets.
5
4
  Expose local servers to the internet with a simple CLI.
6
5
 
7
-
8
- INSTALLATION
9
- ------------
6
+ ## INSTALLATION
10
7
 
11
8
  npm install -g traforo
12
9
 
13
-
14
- USAGE
15
- -----
10
+ ## USAGE
16
11
 
17
12
  Expose a local server:
18
13
 
19
14
  traforo -p 3000
20
15
 
21
- With a custom tunnel ID:
16
+ With a custom tunnel ID (only for services safe to expose publicly):
22
17
 
23
18
  traforo -p 3000 -t my-app
24
19
 
@@ -32,20 +27,16 @@ The tunnel URL will be:
32
27
 
33
28
  https://{tunnel-id}-tunnel.traforo.dev
34
29
 
35
-
36
- OPTIONS
37
- -------
30
+ ## OPTIONS
38
31
 
39
32
  -p, --port <port> Local port to expose (required)
40
- -t, --tunnel-id [id] Tunnel ID (random if omitted)
33
+ -t, --tunnel-id [id] Custom tunnel ID (prefer random default)
41
34
  -h, --host [host] Local host (default: localhost)
42
35
  -s, --server [url] Custom tunnel server URL
43
36
  --help Show help
44
37
  --version Show version
45
38
 
46
-
47
- HOW IT WORKS
48
- ------------
39
+ ## HOW IT WORKS
49
40
 
50
41
  1. Local client connects to Cloudflare Durable Object via WebSocket
51
42
  2. HTTP requests to tunnel URL are forwarded to the DO
@@ -53,17 +44,13 @@ HOW IT WORKS
53
44
  4. Local client makes request to localhost and returns response
54
45
  5. WebSocket connections from users are also proxied through
55
46
 
56
-
57
- API ENDPOINTS
58
- -------------
47
+ ## API ENDPOINTS
59
48
 
60
49
  /traforo-status Check if tunnel is online
61
50
  /traforo-upstream WebSocket endpoint for local client
62
51
  /* All other paths proxied to local server
63
52
 
64
-
65
- LIBRARY USAGE
66
- -------------
53
+ ## LIBRARY USAGE
67
54
 
68
55
  import { TunnelClient } from 'traforo/client'
69
56
  import { runTunnel } from 'traforo/run-tunnel'
@@ -75,8 +62,6 @@ LIBRARY USAGE
75
62
 
76
63
  await client.connect()
77
64
 
78
-
79
- LICENSE
80
- -------
65
+ ## LICENSE
81
66
 
82
67
  MIT
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ const cli = goke(CLI_NAME);
6
6
  cli
7
7
  .command('', 'Expose a local port via tunnel')
8
8
  .option('-p, --port <port>', 'Local port to expose (required)')
9
- .option('-t, --tunnel-id [id]', 'Tunnel ID (random if omitted)')
9
+ .option('-t, --tunnel-id [id]', 'Custom tunnel ID (only for services safe to expose publicly; prefer random default)')
10
10
  .option('-h, --host [host]', 'Local host (default: localhost)')
11
11
  .option('-s, --server [url]', 'Tunnel server URL')
12
12
  .example(`${CLI_NAME} -p 3000`)
package/dist/client.js CHANGED
@@ -240,22 +240,15 @@ export class TunnelClient {
240
240
  this.localWsConnections.delete(msg.connId);
241
241
  });
242
242
  localWs.on('message', (data, isBinary) => {
243
- let frameData;
244
- let binary = false;
245
- if (isBinary || data instanceof Buffer) {
246
- frameData = Buffer.isBuffer(data)
247
- ? data.toString('base64')
248
- : Buffer.from(data).toString('base64');
249
- binary = true;
250
- }
251
- else {
252
- frameData = data.toString();
253
- }
243
+ const dataBuffer = rawDataToBuffer(data);
244
+ const frameData = isBinary
245
+ ? dataBuffer.toString('base64')
246
+ : dataBuffer.toString('utf8');
254
247
  const frame = {
255
248
  type: 'ws_frame',
256
249
  connId: msg.connId,
257
250
  data: frameData,
258
- binary,
251
+ binary: isBinary,
259
252
  };
260
253
  this.send(frame);
261
254
  });
@@ -309,3 +302,12 @@ export class TunnelClient {
309
302
  this.ws.send(JSON.stringify(msg));
310
303
  }
311
304
  }
305
+ function rawDataToBuffer(data) {
306
+ if (Buffer.isBuffer(data)) {
307
+ return data;
308
+ }
309
+ if (Array.isArray(data)) {
310
+ return Buffer.concat(data.map((chunk) => rawDataToBuffer(chunk)));
311
+ }
312
+ return Buffer.from(data);
313
+ }
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import net from 'node:net';
3
3
  import { TunnelClient } from './client.js';
4
4
  export const CLI_NAME = 'traforo';
5
+ const DEFAULT_TUNNEL_ID_LENGTH = 16;
5
6
  /**
6
7
  * Wait for a port to be available (accepting connections).
7
8
  * Used when spawning a child process to wait for the server to start.
@@ -47,7 +48,8 @@ export function parseCommandFromArgv(argv) {
47
48
  * Run the tunnel, optionally spawning a child process first.
48
49
  */
49
50
  export async function runTunnel(options) {
50
- const tunnelId = options.tunnelId || crypto.randomUUID().slice(0, 8);
51
+ const tunnelId = options.tunnelId ||
52
+ crypto.randomUUID().replaceAll('-', '').slice(0, DEFAULT_TUNNEL_ID_LENGTH);
51
53
  const localHost = options.localHost || 'localhost';
52
54
  const port = options.port;
53
55
  let child = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "traforo",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "HTTP tunnel via Cloudflare Durable Objects and WebSockets",
5
5
  "type": "module",
6
6
  "license": "MIT",