fbi-proxy 1.8.1 → 1.9.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 +13 -6
- package/dist/cli.js +20 -6
- package/package.json +1 -1
- package/release/fbi-proxy-linux-arm64 +0 -0
- package/release/fbi-proxy-linux-x64 +0 -0
- package/release/fbi-proxy-macos-arm64 +0 -0
- package/release/fbi-proxy-macos-x64 +0 -0
- package/release/fbi-proxy-windows-arm64.exe +0 -0
- package/release/fbi-proxy-windows-x64.exe +0 -0
- package/rs/fbi-proxy.rs +133 -9
- package/ts/buildFbiProxy.ts +21 -2
- package/ts/cli.ts +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# fbi-proxy
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/fbi-proxy)
|
|
4
|
+
[](https://crates.io/crates/fbi-proxy)
|
|
5
|
+
[](https://github.com/snomiao/fbi-proxy/releases/latest)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
3
8
|
FBI-Proxy provides easy HTTPS access to your local services with intelligent domain routing.
|
|
4
9
|
|
|
5
10
|
## Features
|
|
@@ -22,12 +27,14 @@ FBI-Proxy provides easy HTTPS access to your local services with intelligent dom
|
|
|
22
27
|
## Roadmap
|
|
23
28
|
|
|
24
29
|
### Next Up 🚧
|
|
30
|
+
|
|
25
31
|
- [ ] **Configuration File Support** - YAML/JSON config for persistent routing rules
|
|
26
32
|
- [ ] **Access Control** - Domain filtering, host/port whitelisting
|
|
27
33
|
- [ ] **Request Logging** - Basic access logs for debugging
|
|
28
34
|
- [ ] **Health Checks** - Simple upstream service availability monitoring
|
|
29
35
|
|
|
30
36
|
### Future Improvements 🔮
|
|
37
|
+
|
|
31
38
|
- [ ] **Load Balancing** - Round-robin between multiple upstream targets
|
|
32
39
|
- [ ] **Metrics** - Basic statistics (requests, response times, errors)
|
|
33
40
|
- [ ] **Hot Reload** - Update configuration without restart
|
|
@@ -134,12 +141,12 @@ bun run build && bun run start
|
|
|
134
141
|
|
|
135
142
|
FBI-Proxy supports the following environment variables for configuration:
|
|
136
143
|
|
|
137
|
-
| Variable
|
|
138
|
-
|
|
139
|
-
| `FBI_PROXY_PORT` | Port for the proxy server to listen on
|
|
140
|
-
| `FBI_PROXY_HOST` | Host/IP address to bind to
|
|
141
|
-
| `RUST_LOG`
|
|
142
|
-
| `FBIPROXY_PORT`
|
|
144
|
+
| Variable | Description | Default |
|
|
145
|
+
| ---------------- | -------------------------------------------------------------- | ----------- |
|
|
146
|
+
| `FBI_PROXY_PORT` | Port for the proxy server to listen on | `2432` |
|
|
147
|
+
| `FBI_PROXY_HOST` | Host/IP address to bind to | `127.0.0.1` |
|
|
148
|
+
| `RUST_LOG` | Log level for the Rust proxy (error, warn, info, debug, trace) | `info` |
|
|
149
|
+
| `FBIPROXY_PORT` | Internal proxy port (auto-assigned) | Auto |
|
|
143
150
|
|
|
144
151
|
Command-line arguments take precedence over environment variables.
|
|
145
152
|
|
package/dist/cli.js
CHANGED
|
@@ -132,7 +132,7 @@ async function hotMemo(fn, args = [], key = `_HOTMEMO_${g["_HOTMEMO_SALT_"]}_${S
|
|
|
132
132
|
hotMemo.cache = cache;
|
|
133
133
|
|
|
134
134
|
// ts/cli.ts
|
|
135
|
-
import
|
|
135
|
+
import path2 from "path";
|
|
136
136
|
|
|
137
137
|
// node_modules/yargs/lib/platform-shims/esm.mjs
|
|
138
138
|
import { notStrictEqual, strictEqual } from "assert";
|
|
@@ -4990,6 +4990,7 @@ var yargs_default = Yargs;
|
|
|
4990
4990
|
// ts/buildFbiProxy.ts
|
|
4991
4991
|
import { existsSync } from "fs";
|
|
4992
4992
|
import { chmod } from "fs/promises";
|
|
4993
|
+
import path from "path";
|
|
4993
4994
|
|
|
4994
4995
|
// ts/getProxyFilename.ts
|
|
4995
4996
|
function getFbiProxyFilename() {
|
|
@@ -5117,15 +5118,27 @@ var $ = Object.assign(dSpawn(), {
|
|
|
5117
5118
|
|
|
5118
5119
|
// ts/buildFbiProxy.ts
|
|
5119
5120
|
if (false) {}
|
|
5120
|
-
async function getFbiProxyBinary({
|
|
5121
|
+
async function getFbiProxyBinary({
|
|
5122
|
+
rebuild = false,
|
|
5123
|
+
originalCwd = ""
|
|
5124
|
+
} = {}) {
|
|
5121
5125
|
const isWin = process.platform === "win32";
|
|
5122
5126
|
const binaryName = getFbiProxyFilename();
|
|
5127
|
+
const binarySuffix = isWin ? ".exe" : "";
|
|
5128
|
+
if (!rebuild && originalCwd) {
|
|
5129
|
+
const localBuilt = path.join(originalCwd, `target/release/fbi-proxy${binarySuffix}`);
|
|
5130
|
+
if (existsSync(localBuilt)) {
|
|
5131
|
+
console.log(`Using local build: ${localBuilt}`);
|
|
5132
|
+
await chmod(localBuilt, 493).catch(() => {});
|
|
5133
|
+
return localBuilt;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5123
5136
|
const dockerBinary = "/app/bin/fbi-proxy";
|
|
5124
5137
|
if (!rebuild && existsSync(dockerBinary)) {
|
|
5125
5138
|
return dockerBinary;
|
|
5126
5139
|
}
|
|
5127
5140
|
const release = "./release/" + binaryName;
|
|
5128
|
-
const built = `./target/release/fbi-proxy${
|
|
5141
|
+
const built = `./target/release/fbi-proxy${binarySuffix}`;
|
|
5129
5142
|
if (!rebuild && existsSync(built)) {
|
|
5130
5143
|
await chmod(built, 493).catch(() => {});
|
|
5131
5144
|
return built;
|
|
@@ -5222,11 +5235,12 @@ var dSpawn2 = ({
|
|
|
5222
5235
|
});
|
|
5223
5236
|
var $2 = Object.assign(dSpawn2(), {
|
|
5224
5237
|
opt: dSpawn2,
|
|
5225
|
-
cwd: (
|
|
5238
|
+
cwd: (path2) => dSpawn2({ cwd: path2 })
|
|
5226
5239
|
});
|
|
5227
5240
|
|
|
5228
5241
|
// ts/cli.ts
|
|
5229
|
-
process.
|
|
5242
|
+
var originalCwd = process.cwd();
|
|
5243
|
+
process.chdir(path2.resolve(import.meta.dir, ".."));
|
|
5230
5244
|
await yargs_default(hideBin(process.argv)).option("dev", {
|
|
5231
5245
|
alias: "d",
|
|
5232
5246
|
type: "boolean",
|
|
@@ -5236,7 +5250,7 @@ await yargs_default(hideBin(process.argv)).option("dev", {
|
|
|
5236
5250
|
console.log("Preparing Binaries");
|
|
5237
5251
|
var FBI_PROXY_PORT = process.env.FBI_PROXY_PORT || String(await getPorts({ port: 2432 }));
|
|
5238
5252
|
var proxyProcess = await hotMemo(async () => {
|
|
5239
|
-
const proxy = await getFbiProxyBinary();
|
|
5253
|
+
const proxy = await getFbiProxyBinary({ originalCwd });
|
|
5240
5254
|
console.log("Starting Rust proxy server");
|
|
5241
5255
|
const p = $2.opt({
|
|
5242
5256
|
env: {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/rs/fbi-proxy.rs
CHANGED
|
@@ -75,6 +75,96 @@ impl FBIProxy {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
fn landing_page_html() -> String {
|
|
79
|
+
r#"<!DOCTYPE html>
|
|
80
|
+
<html lang="en">
|
|
81
|
+
<head>
|
|
82
|
+
<meta charset="UTF-8">
|
|
83
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
84
|
+
<title>FBI-Proxy</title>
|
|
85
|
+
<style>
|
|
86
|
+
* { box-sizing: border-box; }
|
|
87
|
+
body {
|
|
88
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, monospace;
|
|
89
|
+
max-width: 800px;
|
|
90
|
+
margin: 0 auto;
|
|
91
|
+
padding: 2rem;
|
|
92
|
+
background: #0d1117;
|
|
93
|
+
color: #c9d1d9;
|
|
94
|
+
line-height: 1.6;
|
|
95
|
+
}
|
|
96
|
+
h1 { color: #58a6ff; margin-bottom: 0.5rem; }
|
|
97
|
+
h2 { color: #8b949e; border-bottom: 1px solid #30363d; padding-bottom: 0.5rem; }
|
|
98
|
+
code {
|
|
99
|
+
background: #161b22;
|
|
100
|
+
padding: 0.2rem 0.4rem;
|
|
101
|
+
border-radius: 4px;
|
|
102
|
+
font-size: 0.9em;
|
|
103
|
+
}
|
|
104
|
+
pre {
|
|
105
|
+
background: #161b22;
|
|
106
|
+
padding: 1rem;
|
|
107
|
+
border-radius: 8px;
|
|
108
|
+
overflow-x: auto;
|
|
109
|
+
}
|
|
110
|
+
table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
|
|
111
|
+
th, td {
|
|
112
|
+
text-align: left;
|
|
113
|
+
padding: 0.5rem;
|
|
114
|
+
border-bottom: 1px solid #30363d;
|
|
115
|
+
}
|
|
116
|
+
th { color: #8b949e; }
|
|
117
|
+
.arrow { color: #7ee787; }
|
|
118
|
+
a { color: #58a6ff; }
|
|
119
|
+
.warning {
|
|
120
|
+
background: #3d1f00;
|
|
121
|
+
border: 1px solid #f85149;
|
|
122
|
+
padding: 1rem;
|
|
123
|
+
border-radius: 8px;
|
|
124
|
+
margin: 1rem 0;
|
|
125
|
+
}
|
|
126
|
+
</style>
|
|
127
|
+
</head>
|
|
128
|
+
<body>
|
|
129
|
+
<h1>🔀 FBI-Proxy</h1>
|
|
130
|
+
<p>A reverse proxy with intelligent host header routing.</p>
|
|
131
|
+
|
|
132
|
+
<h2>How It Works</h2>
|
|
133
|
+
<p>FBI-Proxy routes requests based on the <code>Host</code> header:</p>
|
|
134
|
+
<table>
|
|
135
|
+
<tr><th>Host Header</th><th></th><th>Routes To</th><th>Description</th></tr>
|
|
136
|
+
<tr><td><code>3000</code></td><td class="arrow">→</td><td><code>localhost:3000</code></td><td>Port as host</td></tr>
|
|
137
|
+
<tr><td><code>api--8080</code></td><td class="arrow">→</td><td><code>api:8080</code></td><td>host--port syntax</td></tr>
|
|
138
|
+
<tr><td><code>3000.fbi.com</code></td><td class="arrow">→</td><td><code>localhost:3000</code></td><td>Subdomain as port</td></tr>
|
|
139
|
+
<tr><td><code>app.server</code></td><td class="arrow">→</td><td><code>server:80</code></td><td>Subdomain hoisting</td></tr>
|
|
140
|
+
</table>
|
|
141
|
+
|
|
142
|
+
<h2>Quick Start</h2>
|
|
143
|
+
<pre>npx fbi-proxy # Start proxy on :2432
|
|
144
|
+
npx fbi-proxy -d fbi.example.com # Only accept *.fbi.example.com</pre>
|
|
145
|
+
|
|
146
|
+
<h2>Caddy Setup</h2>
|
|
147
|
+
<p>Expose local ports via HTTPS with wildcard domain:</p>
|
|
148
|
+
<pre># Caddyfile
|
|
149
|
+
*.fbi.example.com {
|
|
150
|
+
tls { dns cloudflare {env.CF_API_TOKEN} }
|
|
151
|
+
reverse_proxy localhost:2432
|
|
152
|
+
}</pre>
|
|
153
|
+
<p>Then access:</p>
|
|
154
|
+
<ul>
|
|
155
|
+
<li><code>https://3000.fbi.example.com</code> → <code>localhost:3000</code></li>
|
|
156
|
+
<li><code>https://8080.fbi.example.com</code> → <code>localhost:8080</code></li>
|
|
157
|
+
</ul>
|
|
158
|
+
|
|
159
|
+
<div class="warning">
|
|
160
|
+
⚠️ <strong>Security Warning:</strong> Set up an auth gateway before exposing to the internet.
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<p><a href="https://github.com/snomiao/fbi-proxy">GitHub</a> · <a href="https://www.npmjs.com/package/fbi-proxy">npm</a> · <a href="https://crates.io/crates/fbi-proxy">crates.io</a></p>
|
|
164
|
+
</body>
|
|
165
|
+
</html>"#.to_string()
|
|
166
|
+
}
|
|
167
|
+
|
|
78
168
|
fn parse_host(&self, host_header: &str, domain_filter: &Option<String>) -> Option<(String, String)> {
|
|
79
169
|
// Remove port if present (e.g., "localhost:8080" -> "localhost")
|
|
80
170
|
let host_without_port = if let Some(colon_pos) = host_header.find(':') {
|
|
@@ -113,9 +203,9 @@ impl FBIProxy {
|
|
|
113
203
|
host_without_port
|
|
114
204
|
};
|
|
115
205
|
|
|
116
|
-
// Handle special case: @ means root domain was accessed
|
|
206
|
+
// Handle special case: @ means root domain was accessed - serve landing page
|
|
117
207
|
if host == "@" {
|
|
118
|
-
return Some(("
|
|
208
|
+
return Some(("@LANDING".to_string(), "@LANDING".to_string()));
|
|
119
209
|
}
|
|
120
210
|
|
|
121
211
|
// Rule 1: number host goes to local port (e.g., "3000" => "localhost:3000")
|
|
@@ -177,7 +267,16 @@ impl FBIProxy {
|
|
|
177
267
|
.body(Full::new(Bytes::from("Bad Gateway: Host not allowed")).map_err(|e| match e {}).boxed())?);
|
|
178
268
|
}
|
|
179
269
|
};
|
|
180
|
-
|
|
270
|
+
|
|
271
|
+
// Serve landing page for root domain access
|
|
272
|
+
if target_host == "@LANDING" {
|
|
273
|
+
info!("GET {} => LANDING 200", host_header);
|
|
274
|
+
return Ok(Response::builder()
|
|
275
|
+
.status(StatusCode::OK)
|
|
276
|
+
.header("Content-Type", "text/html; charset=utf-8")
|
|
277
|
+
.body(Full::new(Bytes::from(Self::landing_page_html())).map_err(|e| match e {}).boxed())?);
|
|
278
|
+
}
|
|
279
|
+
|
|
181
280
|
let method = req.method().clone();
|
|
182
281
|
let original_uri = req.uri().clone();
|
|
183
282
|
|
|
@@ -285,7 +384,8 @@ impl FBIProxy {
|
|
|
285
384
|
);
|
|
286
385
|
return Ok(Response::builder()
|
|
287
386
|
.status(StatusCode::BAD_GATEWAY)
|
|
288
|
-
.
|
|
387
|
+
.header("Content-Type", "text/plain")
|
|
388
|
+
.body(Full::new(Bytes::from(format!("502 Bad Gateway: failed to connect to {}: {}", tunnel_target, e))).map_err(|e| match e {}).boxed())?);
|
|
289
389
|
}
|
|
290
390
|
Err(_) => {
|
|
291
391
|
error!(
|
|
@@ -296,7 +396,8 @@ impl FBIProxy {
|
|
|
296
396
|
);
|
|
297
397
|
return Ok(Response::builder()
|
|
298
398
|
.status(StatusCode::BAD_GATEWAY)
|
|
299
|
-
.
|
|
399
|
+
.header("Content-Type", "text/plain")
|
|
400
|
+
.body(Full::new(Bytes::from(format!("502 Bad Gateway: connection to {} timed out", tunnel_target))).map_err(|e| match e {}).boxed())?);
|
|
300
401
|
}
|
|
301
402
|
}
|
|
302
403
|
}
|
|
@@ -363,7 +464,8 @@ impl FBIProxy {
|
|
|
363
464
|
);
|
|
364
465
|
Ok(Response::builder()
|
|
365
466
|
.status(StatusCode::BAD_GATEWAY)
|
|
366
|
-
.
|
|
467
|
+
.header("Content-Type", "text/plain")
|
|
468
|
+
.body(Full::new(Bytes::from(format!("502 Bad Gateway: failed to connect to {}: {}", target_host, e))).map_err(|e| match e {}).boxed())?)
|
|
367
469
|
}
|
|
368
470
|
Err(_) => {
|
|
369
471
|
error!(
|
|
@@ -375,7 +477,8 @@ impl FBIProxy {
|
|
|
375
477
|
);
|
|
376
478
|
Ok(Response::builder()
|
|
377
479
|
.status(StatusCode::BAD_GATEWAY)
|
|
378
|
-
.
|
|
480
|
+
.header("Content-Type", "text/plain")
|
|
481
|
+
.body(Full::new(Bytes::from(format!("502 Bad Gateway: request to {} timed out", target_host))).map_err(|e| match e {}).boxed())?)
|
|
379
482
|
}
|
|
380
483
|
}
|
|
381
484
|
}
|
|
@@ -401,7 +504,8 @@ impl FBIProxy {
|
|
|
401
504
|
error!("WS :ws:{} => :ws:{}{} 502 (upstream connection failed: {})", target_host, target_host, uri, e);
|
|
402
505
|
return Ok(Response::builder()
|
|
403
506
|
.status(StatusCode::BAD_GATEWAY)
|
|
404
|
-
.
|
|
507
|
+
.header("Content-Type", "text/plain")
|
|
508
|
+
.body(Full::new(Bytes::from(format!("502 Bad Gateway: WebSocket upstream {} unavailable: {}", target_host, e))).map_err(|e| match e {}).boxed())?);
|
|
405
509
|
}
|
|
406
510
|
};
|
|
407
511
|
|
|
@@ -479,7 +583,8 @@ async fn handle_connection(
|
|
|
479
583
|
error!("Request handling error: {}", e);
|
|
480
584
|
Ok(Response::builder()
|
|
481
585
|
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
|
482
|
-
.
|
|
586
|
+
.header("Content-Type", "text/plain")
|
|
587
|
+
.body(Full::new(Bytes::from(format!("500 Internal Server Error: {}", e))).map_err(|e| match e {}).boxed())
|
|
483
588
|
.unwrap())
|
|
484
589
|
}
|
|
485
590
|
}
|
|
@@ -499,6 +604,25 @@ pub async fn start_proxy_server(host: Option<&str>, port: u16, domain_filter: Op
|
|
|
499
604
|
println!("Domain filter: Only accepting requests for *.{}", domain);
|
|
500
605
|
}
|
|
501
606
|
}
|
|
607
|
+
println!();
|
|
608
|
+
println!("== HOW IT WORKS ==");
|
|
609
|
+
println!("Routes requests based on Host header:");
|
|
610
|
+
println!(" 3000 -> localhost:3000 (port as host)");
|
|
611
|
+
println!(" api--8080 -> api:8080 (host--port syntax)");
|
|
612
|
+
println!(" 3000.fbi.com -> localhost:3000 (subdomain as port)");
|
|
613
|
+
println!(" app.server -> server:80 (subdomain hoisting)");
|
|
614
|
+
println!();
|
|
615
|
+
println!("== CADDY SETUP ==");
|
|
616
|
+
println!("# Caddyfile - expose *.fbi.example.com to local ports");
|
|
617
|
+
println!("*.fbi.example.com {{");
|
|
618
|
+
println!(" tls {{ dns cloudflare {{env.CF_API_TOKEN}} }}");
|
|
619
|
+
println!(" reverse_proxy localhost:2432");
|
|
620
|
+
println!("}}");
|
|
621
|
+
println!();
|
|
622
|
+
println!("Then: fbi-proxy -d fbi.example.com");
|
|
623
|
+
println!(" https://3000.fbi.example.com -> localhost:3000");
|
|
624
|
+
println!(" https://8080.fbi.example.com -> localhost:8080");
|
|
625
|
+
println!();
|
|
502
626
|
println!("⚠️ FBI-Proxy WARNING: ENSURE YOU KNOW WHAT YOU'RE DOING and be sure to set up an auth gateway before exposing to the internet");
|
|
503
627
|
println!(" This proxy is production ready but requires proper security measures.");
|
|
504
628
|
|
package/ts/buildFbiProxy.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import { chmod } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
3
4
|
import { getFbiProxyFilename } from "./getProxyFilename";
|
|
4
5
|
import { $ } from "./dSpawn";
|
|
5
6
|
|
|
@@ -7,9 +8,27 @@ if (import.meta.main) {
|
|
|
7
8
|
await getFbiProxyBinary();
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export async function getFbiProxyBinary({
|
|
11
|
+
export async function getFbiProxyBinary({
|
|
12
|
+
rebuild = false,
|
|
13
|
+
originalCwd = "",
|
|
14
|
+
} = {}) {
|
|
11
15
|
const isWin = process.platform === "win32";
|
|
12
16
|
const binaryName = getFbiProxyFilename();
|
|
17
|
+
const binarySuffix = isWin ? ".exe" : "";
|
|
18
|
+
|
|
19
|
+
// Check for local build in original working directory first
|
|
20
|
+
// This allows users to run `bunx fbi-proxy` from their local repo and use their own build
|
|
21
|
+
if (!rebuild && originalCwd) {
|
|
22
|
+
const localBuilt = path.join(
|
|
23
|
+
originalCwd,
|
|
24
|
+
`target/release/fbi-proxy${binarySuffix}`,
|
|
25
|
+
);
|
|
26
|
+
if (existsSync(localBuilt)) {
|
|
27
|
+
console.log(`Using local build: ${localBuilt}`);
|
|
28
|
+
await chmod(localBuilt, 0o755).catch(() => {});
|
|
29
|
+
return localBuilt;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
13
32
|
|
|
14
33
|
// Check for pre-built binary in Docker container
|
|
15
34
|
const dockerBinary = "/app/bin/fbi-proxy";
|
|
@@ -18,7 +37,7 @@ export async function getFbiProxyBinary({ rebuild = false } = {}) {
|
|
|
18
37
|
}
|
|
19
38
|
|
|
20
39
|
const release = "./release/" + binaryName;
|
|
21
|
-
const built = `./target/release/fbi-proxy${
|
|
40
|
+
const built = `./target/release/fbi-proxy${binarySuffix}`;
|
|
22
41
|
|
|
23
42
|
// return built if exists
|
|
24
43
|
if (!rebuild && existsSync(built)) {
|
package/ts/cli.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { hideBin } from "yargs/helpers";
|
|
|
7
7
|
import { getFbiProxyBinary } from "./buildFbiProxy";
|
|
8
8
|
import { $ } from "./dSpawn";
|
|
9
9
|
|
|
10
|
+
// Save original cwd before changing (user might have local build there)
|
|
11
|
+
const originalCwd = process.cwd();
|
|
10
12
|
process.chdir(path.resolve(import.meta.dir, "..")); // Change to project root directory
|
|
11
13
|
|
|
12
14
|
// Parse command line arguments with yargs
|
|
@@ -25,7 +27,7 @@ const FBI_PROXY_PORT =
|
|
|
25
27
|
process.env.FBI_PROXY_PORT || String(await getPort({ port: 2432 }));
|
|
26
28
|
|
|
27
29
|
const proxyProcess = await hotMemo(async () => {
|
|
28
|
-
const proxy = await getFbiProxyBinary();
|
|
30
|
+
const proxy = await getFbiProxyBinary({ originalCwd });
|
|
29
31
|
console.log("Starting Rust proxy server");
|
|
30
32
|
const p = $.opt({
|
|
31
33
|
env: {
|