@bifrost-proxy/bifrost 0.0.42-beta → 0.0.44-beta

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.
Files changed (3) hide show
  1. package/install.js +206 -0
  2. package/lib/index.js +47 -11
  3. package/package.json +14 -8
package/install.js ADDED
@@ -0,0 +1,206 @@
1
+ const fs = require("fs");
2
+ const os = require("os");
3
+ const path = require("path");
4
+ const zlib = require("zlib");
5
+ const https = require("https");
6
+ const child_process = require("child_process");
7
+
8
+ const packageJSON = require(path.join(__dirname, "package.json"));
9
+
10
+ const PLATFORM_MAP = {
11
+ "linux-x64-glibc": { pkg: "@bifrost-proxy/bifrost-linux-x64", binary: "bifrost" },
12
+ "linux-x64-musl": { pkg: "@bifrost-proxy/bifrost-linux-x64-musl", binary: "bifrost" },
13
+ "linux-arm64-glibc": { pkg: "@bifrost-proxy/bifrost-linux-arm64", binary: "bifrost" },
14
+ "linux-arm64-musl": { pkg: "@bifrost-proxy/bifrost-linux-arm64-musl", binary: "bifrost" },
15
+ "linux-arm-glibc": { pkg: "@bifrost-proxy/bifrost-linux-arm", binary: "bifrost" },
16
+ "darwin-x64": { pkg: "@bifrost-proxy/bifrost-darwin-x64", binary: "bifrost" },
17
+ "darwin-arm64": { pkg: "@bifrost-proxy/bifrost-darwin-arm64", binary: "bifrost" },
18
+ "win32-x64": { pkg: "@bifrost-proxy/bifrost-win32-x64", binary: "bifrost.exe" },
19
+ "win32-arm64": { pkg: "@bifrost-proxy/bifrost-win32-arm64", binary: "bifrost.exe" },
20
+ };
21
+
22
+ function detectLibc() {
23
+ if (process.platform !== "linux") return null;
24
+ try {
25
+ const lddOutput = child_process.execSync("ldd --version 2>&1 || true", {
26
+ stdio: ["pipe", "pipe", "pipe"],
27
+ encoding: "utf8",
28
+ });
29
+ if (/musl/i.test(lddOutput)) return "musl";
30
+ if (/GLIBC|GNU libc/i.test(lddOutput)) return "glibc";
31
+ } catch {}
32
+ try {
33
+ if (fs.existsSync("/lib/ld-musl-x86_64.so.1") ||
34
+ fs.existsSync("/lib/ld-musl-aarch64.so.1") ||
35
+ fs.existsSync("/lib/ld-musl-armhf.so.1")) {
36
+ return "musl";
37
+ }
38
+ } catch {}
39
+ return "glibc";
40
+ }
41
+
42
+ function getPlatformInfo() {
43
+ let key = `${process.platform}-${os.arch()}`;
44
+ if (process.platform === "linux") {
45
+ const libc = detectLibc();
46
+ key = `${key}-${libc}`;
47
+ }
48
+ const info = PLATFORM_MAP[key];
49
+ if (!info) {
50
+ throw new Error(
51
+ `Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
52
+ );
53
+ }
54
+ return { ...info, key, subpath: `bin/${info.binary}` };
55
+ }
56
+
57
+ function downloadedBinPath(pkg, binary) {
58
+ return path.join(__dirname, `downloaded-${pkg.replace("/", "-").replace("@", "")}-${binary}`);
59
+ }
60
+
61
+ function fetch(url) {
62
+ return new Promise((resolve, reject) => {
63
+ https.get(url, (res) => {
64
+ if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location)
65
+ return fetch(res.headers.location).then(resolve, reject);
66
+ if (res.statusCode !== 200)
67
+ return reject(new Error(`Server responded with ${res.statusCode}`));
68
+ let chunks = [];
69
+ res.on("data", (chunk) => chunks.push(chunk));
70
+ res.on("end", () => resolve(Buffer.concat(chunks)));
71
+ }).on("error", reject);
72
+ });
73
+ }
74
+
75
+ function extractFileFromTarGzip(buffer, subpath) {
76
+ try {
77
+ buffer = zlib.unzipSync(buffer);
78
+ } catch (err) {
79
+ throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`);
80
+ }
81
+ let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, "");
82
+ let offset = 0;
83
+ subpath = `package/${subpath}`;
84
+ while (offset < buffer.length) {
85
+ let name = str(offset, 100);
86
+ let size = parseInt(str(offset + 124, 12), 8);
87
+ offset += 512;
88
+ if (!isNaN(size)) {
89
+ if (name === subpath) return buffer.subarray(offset, offset + size);
90
+ offset += (size + 511) & ~511;
91
+ }
92
+ }
93
+ throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`);
94
+ }
95
+
96
+ function installUsingNPM(pkg, subpath, binPath) {
97
+ const env = { ...process.env, npm_config_global: void 0 };
98
+ const installDir = path.join(__dirname, "npm-install");
99
+ fs.mkdirSync(installDir, { recursive: true });
100
+ try {
101
+ fs.writeFileSync(path.join(installDir, "package.json"), "{}");
102
+ child_process.execSync(
103
+ `npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${packageJSON.version}`,
104
+ { cwd: installDir, stdio: "pipe", env }
105
+ );
106
+ const installedBinPath = path.join(installDir, "node_modules", pkg, subpath);
107
+ fs.copyFileSync(installedBinPath, binPath);
108
+ fs.chmodSync(binPath, 0o755);
109
+ } finally {
110
+ try {
111
+ removeRecursive(installDir);
112
+ } catch {}
113
+ }
114
+ }
115
+
116
+ function removeRecursive(dir) {
117
+ for (const entry of fs.readdirSync(dir)) {
118
+ const entryPath = path.join(dir, entry);
119
+ let stats;
120
+ try {
121
+ stats = fs.lstatSync(entryPath);
122
+ } catch {
123
+ continue;
124
+ }
125
+ if (stats.isDirectory()) removeRecursive(entryPath);
126
+ else fs.unlinkSync(entryPath);
127
+ }
128
+ fs.rmdirSync(dir);
129
+ }
130
+
131
+ async function downloadDirectlyFromNPM(pkg, subpath, binPath) {
132
+ const tarballName = pkg.replace("@bifrost-proxy/", "");
133
+ const url = `https://registry.npmjs.org/${pkg}/-/${tarballName}-${packageJSON.version}.tgz`;
134
+ console.error(`[bifrost] Trying to download ${JSON.stringify(url)}`);
135
+ try {
136
+ const bytes = extractFileFromTarGzip(await fetch(url), subpath);
137
+ fs.writeFileSync(binPath, bytes);
138
+ fs.chmodSync(binPath, 0o755);
139
+ } catch (e) {
140
+ console.error(`[bifrost] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`);
141
+ throw e;
142
+ }
143
+ }
144
+
145
+ function validateBinary(binPath) {
146
+ try {
147
+ const stdout = child_process
148
+ .execFileSync(binPath, ["--version"], { stdio: "pipe" })
149
+ .toString()
150
+ .trim();
151
+ const version = stdout.replace(/^bifrost\s+/i, "").trim();
152
+ if (version !== packageJSON.version) {
153
+ console.warn(
154
+ `[bifrost] Warning: expected version ${packageJSON.version} but got ${version}`
155
+ );
156
+ }
157
+ } catch {
158
+ // validation is best-effort
159
+ }
160
+ }
161
+
162
+ async function checkAndPreparePackage() {
163
+ const { pkg, binary, subpath } = getPlatformInfo();
164
+
165
+ try {
166
+ const packageDir = path.dirname(require.resolve(`${pkg}/package.json`));
167
+ const binPath = path.join(packageDir, "bin", binary);
168
+ if (fs.existsSync(binPath)) {
169
+ validateBinary(binPath);
170
+ return;
171
+ }
172
+ } catch {}
173
+
174
+ console.error(
175
+ `[bifrost] Failed to find package "${pkg}" on the file system\n\n` +
176
+ `This can happen if you use the "--no-optional" flag. The "optionalDependencies"\n` +
177
+ `feature is used by bifrost to install the correct binary for your current platform.\n` +
178
+ `This install script will now attempt to work around this.\n`
179
+ );
180
+
181
+ const binPath = downloadedBinPath(pkg, binary);
182
+
183
+ try {
184
+ console.error(`[bifrost] Trying to install package "${pkg}" using npm`);
185
+ installUsingNPM(pkg, subpath, binPath);
186
+ validateBinary(binPath);
187
+ return;
188
+ } catch (e) {
189
+ console.error(
190
+ `[bifrost] Failed to install package "${pkg}" using npm: ${e && e.message || e}`
191
+ );
192
+ }
193
+
194
+ try {
195
+ await downloadDirectlyFromNPM(pkg, subpath, binPath);
196
+ validateBinary(binPath);
197
+ return;
198
+ } catch {
199
+ throw new Error(`Failed to install package "${pkg}"`);
200
+ }
201
+ }
202
+
203
+ checkAndPreparePackage().catch((e) => {
204
+ console.error(`[bifrost] ${e && e.message || e}`);
205
+ process.exit(1);
206
+ });
package/lib/index.js CHANGED
@@ -1,18 +1,46 @@
1
1
  const { platform, arch } = process;
2
2
  const path = require("path");
3
+ const fs = require("fs");
4
+ const child_process = require("child_process");
3
5
 
4
6
  const PLATFORM_MAP = {
5
- "linux-x64": "@bifrost-proxy/bifrost-linux-x64",
6
- "linux-arm64": "@bifrost-proxy/bifrost-linux-arm64",
7
- "linux-arm": "@bifrost-proxy/bifrost-linux-arm",
7
+ "linux-x64-glibc": "@bifrost-proxy/bifrost-linux-x64",
8
+ "linux-x64-musl": "@bifrost-proxy/bifrost-linux-x64-musl",
9
+ "linux-arm64-glibc": "@bifrost-proxy/bifrost-linux-arm64",
10
+ "linux-arm64-musl": "@bifrost-proxy/bifrost-linux-arm64-musl",
11
+ "linux-arm-glibc": "@bifrost-proxy/bifrost-linux-arm",
8
12
  "darwin-x64": "@bifrost-proxy/bifrost-darwin-x64",
9
13
  "darwin-arm64": "@bifrost-proxy/bifrost-darwin-arm64",
10
14
  "win32-x64": "@bifrost-proxy/bifrost-win32-x64",
11
15
  "win32-arm64": "@bifrost-proxy/bifrost-win32-arm64",
12
16
  };
13
17
 
18
+ function detectLibc() {
19
+ if (platform !== "linux") return null;
20
+ try {
21
+ const lddOutput = child_process.execSync("ldd --version 2>&1 || true", {
22
+ stdio: ["pipe", "pipe", "pipe"],
23
+ encoding: "utf8",
24
+ });
25
+ if (/musl/i.test(lddOutput)) return "musl";
26
+ if (/GLIBC|GNU libc/i.test(lddOutput)) return "glibc";
27
+ } catch {}
28
+ try {
29
+ if (fs.existsSync("/lib/ld-musl-x86_64.so.1") ||
30
+ fs.existsSync("/lib/ld-musl-aarch64.so.1") ||
31
+ fs.existsSync("/lib/ld-musl-armhf.so.1")) {
32
+ return "musl";
33
+ }
34
+ } catch {}
35
+ return "glibc";
36
+ }
37
+
14
38
  function getBinaryPath() {
15
- const key = `${platform}-${arch}`;
39
+ let key = `${platform}-${arch}`;
40
+ if (platform === "linux") {
41
+ const libc = detectLibc();
42
+ key = `${key}-${libc}`;
43
+ }
16
44
  const packageName = PLATFORM_MAP[key];
17
45
 
18
46
  if (!packageName) {
@@ -26,13 +54,21 @@ function getBinaryPath() {
26
54
 
27
55
  try {
28
56
  const packageDir = path.dirname(require.resolve(`${packageName}/package.json`));
29
- return path.join(packageDir, "bin", binaryName);
30
- } catch {
31
- throw new Error(
32
- `The platform-specific package ${packageName} is not installed. ` +
33
- `Please reinstall @bifrost-proxy/bifrost to fix this.`
34
- );
35
- }
57
+ const binPath = path.join(packageDir, "bin", binaryName);
58
+ if (fs.existsSync(binPath)) return binPath;
59
+ } catch {}
60
+
61
+ const downloadedPath = path.join(
62
+ __dirname,
63
+ "..",
64
+ `downloaded-${packageName.replace("/", "-").replace("@", "")}-${binaryName}`
65
+ );
66
+ if (fs.existsSync(downloadedPath)) return downloadedPath;
67
+
68
+ throw new Error(
69
+ `The platform-specific package ${packageName} is not installed. ` +
70
+ `Please reinstall @bifrost-proxy/bifrost to fix this.`
71
+ );
36
72
  }
37
73
 
38
74
  exports.getBinaryPath = getBinaryPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bifrost-proxy/bifrost",
3
- "version": "0.0.42-beta",
3
+ "version": "0.0.44-beta",
4
4
  "description": "High-performance HTTP/HTTPS/SOCKS5 proxy server written in Rust",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,18 +22,24 @@
22
22
  "bifrost": "bin/bifrost"
23
23
  },
24
24
  "main": "lib/index.js",
25
+ "scripts": {
26
+ "postinstall": "node install.js"
27
+ },
25
28
  "files": [
26
29
  "bin/bifrost",
27
30
  "lib/index.js",
31
+ "install.js",
28
32
  "README.md"
29
33
  ],
30
34
  "optionalDependencies": {
31
- "@bifrost-proxy/bifrost-linux-x64": "0.0.42-beta",
32
- "@bifrost-proxy/bifrost-linux-arm64": "0.0.42-beta",
33
- "@bifrost-proxy/bifrost-linux-arm": "0.0.42-beta",
34
- "@bifrost-proxy/bifrost-darwin-x64": "0.0.42-beta",
35
- "@bifrost-proxy/bifrost-darwin-arm64": "0.0.42-beta",
36
- "@bifrost-proxy/bifrost-win32-x64": "0.0.42-beta",
37
- "@bifrost-proxy/bifrost-win32-arm64": "0.0.42-beta"
35
+ "@bifrost-proxy/bifrost-linux-x64": "0.0.44-beta",
36
+ "@bifrost-proxy/bifrost-linux-arm64": "0.0.44-beta",
37
+ "@bifrost-proxy/bifrost-linux-arm": "0.0.44-beta",
38
+ "@bifrost-proxy/bifrost-linux-x64-musl": "0.0.44-beta",
39
+ "@bifrost-proxy/bifrost-linux-arm64-musl": "0.0.44-beta",
40
+ "@bifrost-proxy/bifrost-darwin-x64": "0.0.44-beta",
41
+ "@bifrost-proxy/bifrost-darwin-arm64": "0.0.44-beta",
42
+ "@bifrost-proxy/bifrost-win32-x64": "0.0.44-beta",
43
+ "@bifrost-proxy/bifrost-win32-arm64": "0.0.44-beta"
38
44
  }
39
45
  }