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 +10 -25
- package/dist/cli.js +1 -1
- package/dist/client.js +14 -12
- package/dist/run-tunnel.js +3 -1
- package/package.json +1 -1
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]
|
|
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]', '
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
+
}
|
package/dist/run-tunnel.js
CHANGED
|
@@ -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 ||
|
|
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;
|