letstunnel 0.1.5
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/bin/cli.js +57 -0
- package/package.json +36 -0
- package/scripts/postinstall.js +100 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execFileSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const PLATFORM_PACKAGES = {
|
|
7
|
+
"darwin-arm64": "@letstunnel/darwin-arm64",
|
|
8
|
+
"darwin-x64": "@letstunnel/darwin-x64",
|
|
9
|
+
"linux-x64": "@letstunnel/linux-x64",
|
|
10
|
+
"win32-x64": "@letstunnel/win32-x64",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const BINARY_NAME = process.platform === "win32" ? "lt.exe" : "lt";
|
|
14
|
+
|
|
15
|
+
function getBinaryPath() {
|
|
16
|
+
const platformKey = `${process.platform}-${process.arch === "arm64" ? "arm64" : "x64"}`;
|
|
17
|
+
const pkg = PLATFORM_PACKAGES[platformKey];
|
|
18
|
+
|
|
19
|
+
if (!pkg) {
|
|
20
|
+
console.error(
|
|
21
|
+
`Error: LetsTunnel does not support ${process.platform}-${process.arch} yet.\n` +
|
|
22
|
+
`Supported platforms: ${Object.keys(PLATFORM_PACKAGES).join(", ")}`
|
|
23
|
+
);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Try to resolve the platform-specific package
|
|
28
|
+
try {
|
|
29
|
+
const pkgDir = path.dirname(require.resolve(`${pkg}/package.json`));
|
|
30
|
+
return path.join(pkgDir, "bin", BINARY_NAME);
|
|
31
|
+
} catch {
|
|
32
|
+
// Fallback: check if binary was installed via postinstall script
|
|
33
|
+
const fallback = path.join(__dirname, BINARY_NAME);
|
|
34
|
+
try {
|
|
35
|
+
require("fs").accessSync(fallback, require("fs").constants.X_OK);
|
|
36
|
+
return fallback;
|
|
37
|
+
} catch {
|
|
38
|
+
console.error(
|
|
39
|
+
`Error: Could not find the LetsTunnel binary.\n` +
|
|
40
|
+
`Expected platform package: ${pkg}\n\n` +
|
|
41
|
+
`Try reinstalling: npm install letstunnel`
|
|
42
|
+
);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const binary = getBinaryPath();
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
execFileSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
52
|
+
} catch (e) {
|
|
53
|
+
if (e.status !== undefined) {
|
|
54
|
+
process.exit(e.status);
|
|
55
|
+
}
|
|
56
|
+
throw e;
|
|
57
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "letstunnel",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Expose your localhost to the world. Public URLs, .local domains, request inspector, and scenario recording.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"tunnel",
|
|
7
|
+
"localhost",
|
|
8
|
+
"webhook",
|
|
9
|
+
"ngrok",
|
|
10
|
+
"port-forwarding",
|
|
11
|
+
"developer-tools",
|
|
12
|
+
"proxy"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://letstunnel.com",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/letstunnel/letstunnel-releases"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"bin": {
|
|
21
|
+
"letstunnel": "bin/cli.js",
|
|
22
|
+
"lt": "bin/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"postinstall": "node scripts/postinstall.js"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"@letstunnel/darwin-arm64": "0.1.5",
|
|
29
|
+
"@letstunnel/darwin-x64": "0.1.5",
|
|
30
|
+
"@letstunnel/linux-x64": "0.1.5",
|
|
31
|
+
"@letstunnel/win32-x64": "0.1.5"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=16"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// Fallback installer: downloads the binary from GitHub releases when the
|
|
4
|
+
// platform-specific optional dependency fails to install (e.g. unsupported
|
|
5
|
+
// npm version, private registry, or missing prebuilt package).
|
|
6
|
+
|
|
7
|
+
const https = require("https");
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const { execSync } = require("child_process");
|
|
11
|
+
|
|
12
|
+
const VERSION = require("../package.json").version;
|
|
13
|
+
const REPO = "letstunnel/letstunnel-releases";
|
|
14
|
+
const BINARY_NAME = process.platform === "win32" ? "lt.exe" : "lt";
|
|
15
|
+
const DEST = path.join(__dirname, "..", "bin", BINARY_NAME);
|
|
16
|
+
|
|
17
|
+
const PLATFORM_MAP = {
|
|
18
|
+
"darwin-arm64": `lt-aarch64-apple-darwin`,
|
|
19
|
+
"darwin-x64": `lt-x86_64-apple-darwin`,
|
|
20
|
+
"linux-x64": `lt-x86_64-unknown-linux-gnu`,
|
|
21
|
+
"win32-x64": `lt-x86_64-pc-windows-msvc.exe`,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function getPlatformKey() {
|
|
25
|
+
const arch = process.arch === "arm64" ? "arm64" : "x64";
|
|
26
|
+
return `${process.platform}-${arch}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function alreadyInstalled() {
|
|
30
|
+
// Check if the platform package already provided the binary
|
|
31
|
+
try {
|
|
32
|
+
const platformKey = getPlatformKey();
|
|
33
|
+
const pkgs = {
|
|
34
|
+
"darwin-arm64": "@letstunnel/darwin-arm64",
|
|
35
|
+
"darwin-x64": "@letstunnel/darwin-x64",
|
|
36
|
+
"linux-x64": "@letstunnel/linux-x64",
|
|
37
|
+
"win32-x64": "@letstunnel/win32-x64",
|
|
38
|
+
};
|
|
39
|
+
const pkg = pkgs[platformKey];
|
|
40
|
+
if (pkg) {
|
|
41
|
+
require.resolve(`${pkg}/package.json`);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// Not installed — fall through to download
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function download(url) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
https.get(url, (res) => {
|
|
53
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
54
|
+
return download(res.headers.location).then(resolve, reject);
|
|
55
|
+
}
|
|
56
|
+
if (res.statusCode !== 200) {
|
|
57
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
58
|
+
}
|
|
59
|
+
const chunks = [];
|
|
60
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
61
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
62
|
+
res.on("error", reject);
|
|
63
|
+
}).on("error", reject);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function main() {
|
|
68
|
+
if (alreadyInstalled()) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const platformKey = getPlatformKey();
|
|
73
|
+
const asset = PLATFORM_MAP[platformKey];
|
|
74
|
+
|
|
75
|
+
if (!asset) {
|
|
76
|
+
console.warn(
|
|
77
|
+
`[letstunnel] No prebuilt binary for ${platformKey}. ` +
|
|
78
|
+
`You can build from source: https://github.com/${REPO}`
|
|
79
|
+
);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${asset}`;
|
|
84
|
+
|
|
85
|
+
console.log(`[letstunnel] Downloading binary for ${platformKey}...`);
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const data = await download(url);
|
|
89
|
+
fs.writeFileSync(DEST, data);
|
|
90
|
+
fs.chmodSync(DEST, 0o755);
|
|
91
|
+
console.log(`[letstunnel] Installed successfully.`);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
console.warn(
|
|
94
|
+
`[letstunnel] Failed to download binary: ${err.message}\n` +
|
|
95
|
+
`You can manually download from: https://github.com/${REPO}/releases`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
main();
|