htn-tunnel 0.2.2 → 0.2.4
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/lib/install.js +59 -92
- package/package.json +1 -1
package/lib/install.js
CHANGED
|
@@ -5,12 +5,12 @@ const os = require("os");
|
|
|
5
5
|
const https = require("https");
|
|
6
6
|
const { execSync } = require("child_process");
|
|
7
7
|
|
|
8
|
-
// Binary version from GitHub Releases
|
|
8
|
+
// Binary version from GitHub Releases.
|
|
9
9
|
const VERSION = "0.2.0";
|
|
10
10
|
const REPO = "nhh0718/htn-tunnel";
|
|
11
11
|
|
|
12
|
-
const platform = os.platform();
|
|
13
|
-
const arch = os.arch();
|
|
12
|
+
const platform = os.platform();
|
|
13
|
+
const arch = os.arch();
|
|
14
14
|
const goOS = platform === "win32" ? "windows" : platform;
|
|
15
15
|
const goArch = arch === "x64" ? "amd64" : arch;
|
|
16
16
|
const ext = platform === "win32" ? ".exe" : "";
|
|
@@ -19,112 +19,79 @@ const archiveExt = platform === "win32" ? ".zip" : ".tar.gz";
|
|
|
19
19
|
const binDir = path.join(__dirname, "..", "bin");
|
|
20
20
|
const binPath = path.join(binDir, `htn-tunnel${ext}`);
|
|
21
21
|
|
|
22
|
-
// Skip if binary
|
|
23
|
-
if (fs.existsSync(binPath) && fs.statSync(binPath).size >
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (out.includes(VERSION)) {
|
|
27
|
-
process.exit(0);
|
|
28
|
-
}
|
|
29
|
-
} catch { /* re-download */ }
|
|
22
|
+
// Skip if binary exists and works.
|
|
23
|
+
if (fs.existsSync(binPath) && fs.statSync(binPath).size > 1000) {
|
|
24
|
+
console.log("htn-tunnel: binary already installed.");
|
|
25
|
+
process.exit(0);
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
const archiveName = `htn-tunnel_${VERSION}_${goOS}_${goArch}${archiveExt}`;
|
|
33
29
|
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
|
|
34
30
|
|
|
35
31
|
console.log(`htn-tunnel: downloading v${VERSION} for ${platform}/${arch}...`);
|
|
36
|
-
console.log(` ${url}`);
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "htn-"));
|
|
34
|
+
const tmpFile = path.join(tmpDir, archiveName);
|
|
35
|
+
|
|
36
|
+
function follow(url, dest, redirects) {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
if (redirects > 5) return reject(new Error("too many redirects"));
|
|
39
|
+
https.get(url, { headers: { "User-Agent": "htn-tunnel-npm" } }, (res) => {
|
|
40
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
41
|
+
return follow(res.headers.location, dest, redirects + 1).then(resolve, reject);
|
|
42
|
+
}
|
|
43
|
+
if (res.statusCode !== 200) {
|
|
44
|
+
return reject(new Error(`HTTP ${res.statusCode}`));
|
|
45
|
+
}
|
|
46
|
+
const file = fs.createWriteStream(dest);
|
|
47
|
+
res.pipe(file);
|
|
48
|
+
file.on("finish", () => { file.close(); resolve(); });
|
|
49
|
+
file.on("error", reject);
|
|
50
|
+
}).on("error", reject);
|
|
49
51
|
});
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
follow(url,
|
|
55
|
-
|
|
56
|
-
console.error(`htn-tunnel: download failed (HTTP ${res.statusCode})`);
|
|
57
|
-
printManual();
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
54
|
+
async function main() {
|
|
55
|
+
try {
|
|
56
|
+
await follow(url, tmpFile, 0);
|
|
57
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (archiveExt === ".zip") {
|
|
67
|
-
extractZip(data, `htn-tunnel${ext}`, binPath);
|
|
68
|
-
} else {
|
|
69
|
-
extractTarGz(data, `htn-tunnel${ext}`, binPath);
|
|
70
|
-
}
|
|
71
|
-
fs.chmodSync(binPath, 0o755);
|
|
72
|
-
console.log("htn-tunnel: installed successfully!");
|
|
73
|
-
} catch (err) {
|
|
74
|
-
console.error("htn-tunnel: extract failed:", err.message);
|
|
75
|
-
printManual();
|
|
76
|
-
process.exit(1);
|
|
59
|
+
if (archiveExt === ".zip") {
|
|
60
|
+
// Windows 10+ has tar that handles zip.
|
|
61
|
+
execSync(`tar -xf "${tmpFile}" -C "${tmpDir}"`, { stdio: "pipe" });
|
|
62
|
+
} else {
|
|
63
|
+
execSync(`tar -xzf "${tmpFile}" -C "${tmpDir}"`, { stdio: "pipe" });
|
|
77
64
|
}
|
|
78
|
-
});
|
|
79
|
-
}, 0);
|
|
80
65
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
offset += Math.ceil(size / 512) * 512;
|
|
66
|
+
// Find the binary in extracted files.
|
|
67
|
+
const binaryName = `htn-tunnel${ext}`;
|
|
68
|
+
const extracted = findFile(tmpDir, binaryName);
|
|
69
|
+
if (!extracted) throw new Error(`${binaryName} not found in archive`);
|
|
70
|
+
|
|
71
|
+
fs.copyFileSync(extracted, binPath);
|
|
72
|
+
fs.chmodSync(binPath, 0o755);
|
|
73
|
+
console.log("htn-tunnel: installed successfully!");
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error("htn-tunnel: install failed:", err.message);
|
|
76
|
+
console.error(`\nInstall manually: https://github.com/${REPO}/releases/tag/v${VERSION}`);
|
|
77
|
+
console.error(`Or: go install github.com/${REPO}/cmd/htn-tunnel@latest\n`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
} finally {
|
|
80
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
97
81
|
}
|
|
98
|
-
throw new Error(`${filename} not found in archive`);
|
|
99
82
|
}
|
|
100
83
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const name = zipData.toString("utf8", offset + 30, offset + 30 + nameLen);
|
|
110
|
-
const dataStart = offset + 30 + nameLen + extraLen;
|
|
111
|
-
if (name.endsWith(filename) || name === filename) {
|
|
112
|
-
if (compMethod === 0) {
|
|
113
|
-
fs.writeFileSync(dest, zipData.subarray(dataStart, dataStart + compSize));
|
|
114
|
-
} else {
|
|
115
|
-
const zlib = require("zlib");
|
|
116
|
-
const raw = zipData.subarray(dataStart, dataStart + compSize);
|
|
117
|
-
fs.writeFileSync(dest, zlib.inflateRawSync(raw));
|
|
118
|
-
}
|
|
119
|
-
return;
|
|
84
|
+
function findFile(dir, name) {
|
|
85
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
86
|
+
const full = path.join(dir, entry.name);
|
|
87
|
+
if (entry.isDirectory()) {
|
|
88
|
+
const found = findFile(full, name);
|
|
89
|
+
if (found) return found;
|
|
90
|
+
} else if (entry.name === name) {
|
|
91
|
+
return full;
|
|
120
92
|
}
|
|
121
|
-
offset = dataStart + compSize;
|
|
122
93
|
}
|
|
123
|
-
|
|
94
|
+
return null;
|
|
124
95
|
}
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
console.error("\nInstall manually:");
|
|
128
|
-
console.error(` https://github.com/${REPO}/releases/tag/v${VERSION}`);
|
|
129
|
-
console.error("\nOr use: go install github.com/nhh0718/htn-tunnel/cmd/htn-tunnel@latest\n");
|
|
130
|
-
}
|
|
97
|
+
main();
|