@rubriclab/bunl 0.0.9 → 0.0.11
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 +37 -5
- package/build/client.js +5 -7
- package/client.ts +3 -6
- package/package.json +8 -7
- package/server.ts +8 -9
package/README.md
CHANGED
|
@@ -2,32 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
## A Bun WebSocket re-write of LocalTunnel
|
|
4
4
|
|
|
5
|
+
### Usage
|
|
6
|
+
|
|
5
7
|
To try it:
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
bun x bunl -p 3000 -d dev.rubric.me -s my-name
|
|
9
11
|
```
|
|
10
12
|
|
|
13
|
+
### Development
|
|
14
|
+
|
|
11
15
|
To install dependencies:
|
|
12
16
|
|
|
13
17
|
```bash
|
|
14
18
|
bun i
|
|
15
19
|
```
|
|
16
20
|
|
|
21
|
+
To run the server:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun server
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
(Optional) to run a dummy process on localhost:3000:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun demo
|
|
31
|
+
```
|
|
32
|
+
|
|
17
33
|
To run the client:
|
|
18
34
|
|
|
19
35
|
```bash
|
|
20
|
-
bun
|
|
36
|
+
bun client -p 3000
|
|
21
37
|
```
|
|
22
38
|
|
|
23
|
-
|
|
39
|
+
With full args:
|
|
24
40
|
|
|
25
41
|
```bash
|
|
26
|
-
bun
|
|
42
|
+
bun client --port 3000 --domain localhost:1234 --subdomain my-subdomain
|
|
27
43
|
```
|
|
28
44
|
|
|
29
|
-
|
|
45
|
+
### [WIP] Deployment
|
|
46
|
+
|
|
47
|
+
To build the client code:
|
|
30
48
|
|
|
31
49
|
```bash
|
|
32
|
-
bun
|
|
50
|
+
bun run build
|
|
33
51
|
```
|
|
52
|
+
|
|
53
|
+
To deploy the server, for example on [Fly](https://fly.io):
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
fly launch && fly deploy
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Making sure to set `DOMAIN` to your domain:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
fly secrets set DOMAIN=example.so
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Open to PRs!
|
package/build/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#! /usr/bin/env
|
|
1
|
+
#! /usr/bin/env bun
|
|
2
|
+
// client.ts
|
|
2
3
|
import { parseArgs } from "util";
|
|
3
4
|
async function main({ url, domain, subdomain }) {
|
|
4
5
|
const serverUrl = `ws://${domain || "localhost:1234"}?new${
|
|
@@ -14,14 +15,11 @@ async function main({ url, domain, subdomain }) {
|
|
|
14
15
|
headers: data.headers,
|
|
15
16
|
})
|
|
16
17
|
.then((res) => res.text())
|
|
17
|
-
.then((res) =>
|
|
18
|
-
socket.send(res);
|
|
19
|
-
});
|
|
18
|
+
.then((res) => socket.send(res));
|
|
20
19
|
}
|
|
21
20
|
});
|
|
22
21
|
socket.addEventListener("open", (event) => {
|
|
23
|
-
|
|
24
|
-
socket.ping();
|
|
22
|
+
if (!event.target.readyState) throw "Not ready";
|
|
25
23
|
});
|
|
26
24
|
}
|
|
27
25
|
var { values } = parseArgs({
|
|
@@ -43,7 +41,7 @@ var { values } = parseArgs({
|
|
|
43
41
|
},
|
|
44
42
|
allowPositionals: true,
|
|
45
43
|
});
|
|
46
|
-
if (!values.port) throw "pass
|
|
44
|
+
if (!values.port) throw "pass -p 3000";
|
|
47
45
|
main({
|
|
48
46
|
url: `localhost:${values.port}`,
|
|
49
47
|
domain: values.domain,
|
package/client.ts
CHANGED
|
@@ -24,15 +24,12 @@ async function main({
|
|
|
24
24
|
headers: data.headers,
|
|
25
25
|
})
|
|
26
26
|
.then((res) => res.text())
|
|
27
|
-
.then((res) =>
|
|
28
|
-
socket.send(res);
|
|
29
|
-
});
|
|
27
|
+
.then((res) => socket.send(res));
|
|
30
28
|
}
|
|
31
29
|
});
|
|
32
30
|
|
|
33
31
|
socket.addEventListener("open", (event) => {
|
|
34
|
-
|
|
35
|
-
socket.ping();
|
|
32
|
+
if (!(event.target as any).readyState) throw "Not ready";
|
|
36
33
|
});
|
|
37
34
|
}
|
|
38
35
|
|
|
@@ -60,7 +57,7 @@ const { values } = parseArgs({
|
|
|
60
57
|
allowPositionals: true,
|
|
61
58
|
});
|
|
62
59
|
|
|
63
|
-
if (!values.port) throw "pass
|
|
60
|
+
if (!values.port) throw "pass -p 3000";
|
|
64
61
|
|
|
65
62
|
main({
|
|
66
63
|
url: `localhost:${values.port}`,
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bin": {
|
|
3
|
-
"bunl": "
|
|
3
|
+
"bunl": "build/client.js"
|
|
4
4
|
},
|
|
5
5
|
"name": "@rubriclab/bunl",
|
|
6
6
|
"description": "expose localhost to the world",
|
|
7
|
-
"version": "0.0.
|
|
7
|
+
"version": "0.0.11",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/RubricLab/bunl.git"
|
|
11
|
+
"url": "git+https://github.com/RubricLab/bunl.git"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"human-id": "^4.1.1"
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@types/bun": "latest"
|
|
18
18
|
},
|
|
19
|
-
"main": "
|
|
19
|
+
"main": "build/client.js",
|
|
20
20
|
"scripts": {
|
|
21
|
-
"server": "bun
|
|
22
|
-
"
|
|
23
|
-
"demo": "bun --hot demo.ts"
|
|
21
|
+
"server": "bun server.ts",
|
|
22
|
+
"client": "bun --hot client.ts",
|
|
23
|
+
"demo": "bun --hot demo.ts",
|
|
24
|
+
"build": "BUILD=build/client.js && bun build client.ts --outdir build --target node && echo -e \"#! /usr/bin/env bun\n$(cat $BUILD)\" > $BUILD"
|
|
24
25
|
},
|
|
25
26
|
"type": "module",
|
|
26
27
|
"peerDependencies": {
|
package/server.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { uid } from "./utils";
|
|
|
4
4
|
type Client = { id: string };
|
|
5
5
|
|
|
6
6
|
const port = Bun.env.PORT || 1234;
|
|
7
|
-
const
|
|
7
|
+
const scheme = Bun.env.SCHEME || "http";
|
|
8
8
|
const domain = Bun.env.DOMAIN || `localhost:${port}`;
|
|
9
9
|
|
|
10
10
|
const clients = new Map<string, ServerWebSocket<Client>>();
|
|
@@ -16,17 +16,17 @@ serve<Client>({
|
|
|
16
16
|
const reqUrl = new URL(req.url);
|
|
17
17
|
|
|
18
18
|
if (reqUrl.searchParams.has("new")) {
|
|
19
|
-
const
|
|
19
|
+
const requested = reqUrl.searchParams.get("subdomain");
|
|
20
|
+
const id = requested && !clients.has(requested) ? requested : uid();
|
|
20
21
|
const upgraded = server.upgrade(req, { data: { id } });
|
|
21
22
|
if (upgraded) return;
|
|
22
|
-
else return new Response("
|
|
23
|
+
else return new Response("upgrade failed", { status: 500 });
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
const subdomain = reqUrl.hostname.split(".")[0];
|
|
26
27
|
|
|
27
28
|
if (!clients.has(subdomain)) {
|
|
28
|
-
|
|
29
|
-
return new Response("client not found :(", { status: 404 });
|
|
29
|
+
return new Response("client not found", { status: 404 });
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// The magic: forward the req to the client
|
|
@@ -42,7 +42,7 @@ serve<Client>({
|
|
|
42
42
|
let res = clientData.get(subdomain);
|
|
43
43
|
|
|
44
44
|
// Poll every second for the client to respond
|
|
45
|
-
// TODO: replace
|
|
45
|
+
// TODO: replace poll with a client-triggered callback
|
|
46
46
|
while (!res) {
|
|
47
47
|
await sleep(1000);
|
|
48
48
|
retries--;
|
|
@@ -63,8 +63,7 @@ serve<Client>({
|
|
|
63
63
|
clients.set(ws.data.id, ws);
|
|
64
64
|
ws.send(
|
|
65
65
|
JSON.stringify({
|
|
66
|
-
|
|
67
|
-
url: `${protocol}://${ws.data.id}.${domain}`,
|
|
66
|
+
url: `${scheme}://${ws.data.id}.${domain}`,
|
|
68
67
|
})
|
|
69
68
|
);
|
|
70
69
|
},
|
|
@@ -73,7 +72,7 @@ serve<Client>({
|
|
|
73
72
|
clientData.set(ws.data.id, message);
|
|
74
73
|
},
|
|
75
74
|
close(ws) {
|
|
76
|
-
console.log(
|
|
75
|
+
console.log("closing", ws.data.id);
|
|
77
76
|
clients.delete(ws.data.id);
|
|
78
77
|
},
|
|
79
78
|
},
|