instatunnel 1.0.28 → 1.0.30

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 (2) hide show
  1. package/install.js +137 -153
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -21,51 +21,31 @@ const colors = {
21
21
  };
22
22
 
23
23
  function log(message, color = 'reset') {
24
- console.log(colors[color] + message + colors.reset);
24
+ console.log(`${colors[color]}${message}${colors.reset}`);
25
25
  }
26
26
 
27
27
  function detectPlatform() {
28
28
  const platform = os.platform();
29
29
  const arch = os.arch();
30
30
 
31
- let platformSuffix;
31
+ // Map to our actual binary names in the bin/ directory
32
32
  switch (platform) {
33
33
  case 'linux':
34
- platformSuffix = 'linux';
35
- break;
34
+ if (arch === 'arm64') {
35
+ return 'instatunnel-linux-arm64';
36
+ }
37
+ return 'instatunnel-linux';
36
38
  case 'darwin':
37
- platformSuffix = 'darwin';
38
- break;
39
+ if (arch === 'arm64') {
40
+ return 'instatunnel-macos-arm64';
41
+ }
42
+ return 'instatunnel-macos';
39
43
  case 'win32':
40
- platformSuffix = 'windows';
41
- break;
42
- case 'freebsd':
43
- platformSuffix = 'freebsd';
44
- break;
45
- case 'openbsd':
46
- platformSuffix = 'openbsd';
47
- break;
48
- default:
49
- throw new Error('Unsupported platform: ' + platform);
50
- }
51
-
52
- let archSuffix;
53
- switch (arch) {
54
- case 'x64':
55
- archSuffix = 'amd64';
56
- break;
57
- case 'arm64':
58
- archSuffix = 'arm64';
59
- break;
60
- case 'ia32':
61
- archSuffix = '386';
62
- break;
44
+ return 'instatunnel-windows.exe';
63
45
  default:
64
- throw new Error('Unsupported architecture: ' + arch);
46
+ // Fallback to linux binary for other Unix-like systems
47
+ return 'instatunnel-linux';
65
48
  }
66
-
67
- const extension = platform === 'win32' ? '.exe' : '';
68
- return { platform: platformSuffix, arch: archSuffix, extension };
69
49
  }
70
50
 
71
51
  function downloadFile(url, outputPath) {
@@ -73,20 +53,29 @@ function downloadFile(url, outputPath) {
73
53
  const file = fs.createWriteStream(outputPath);
74
54
 
75
55
  https.get(url, (response) => {
56
+ // Handle redirects
57
+ if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
58
+ file.close();
59
+ fs.unlinkSync(outputPath);
60
+ return downloadFile(response.headers.location, outputPath).then(resolve).catch(reject);
61
+ }
62
+
76
63
  if (response.statusCode !== 200) {
77
- reject(new Error('Download failed with status: ' + response.statusCode));
64
+ file.close();
65
+ fs.unlinkSync(outputPath);
66
+ reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
78
67
  return;
79
68
  }
80
69
 
81
70
  response.pipe(file);
82
71
 
83
72
  file.on('finish', () => {
84
- file.close();
85
- resolve();
73
+ file.close(resolve);
86
74
  });
87
75
 
88
76
  file.on('error', (err) => {
89
- fs.unlink(outputPath, () => {}); // Delete the file on error
77
+ file.close();
78
+ fs.unlinkSync(outputPath);
90
79
  reject(err);
91
80
  });
92
81
  }).on('error', (err) => {
@@ -95,121 +84,59 @@ function downloadFile(url, outputPath) {
95
84
  });
96
85
  }
97
86
 
98
- async function downloadBinary() {
99
- log('🚀 Installing InstaTunnel CLI...', 'cyan');
87
+ async function setupBinary() {
88
+ const binaryName = detectPlatform();
89
+ const binDir = path.join(__dirname, 'bin');
90
+ const isWindows = os.platform() === 'win32';
91
+ const outputPath = path.join(binDir, isWindows ? 'instatunnel.exe' : 'instatunnel');
92
+ const sourcePath = path.join(binDir, binaryName);
100
93
 
101
- try {
102
- const { platform, arch, extension } = detectPlatform();
103
- const binDir = path.join(__dirname, 'bin');
104
-
105
- // Ensure bin directory exists
106
- if (!fs.existsSync(binDir)) {
107
- fs.mkdirSync(binDir, { recursive: true });
108
- }
109
-
110
- // Use pre-compiled binaries from our package
111
- const sourceBinaryName = BINARY_NAME + '-' + platform + '-' + arch + extension;
112
- const sourceBinaryPath = path.join(binDir, sourceBinaryName);
113
-
114
- if (fs.existsSync(sourceBinaryPath)) {
115
- log('✅ Using pre-compiled binary: ' + sourceBinaryName, 'green');
116
-
117
- // Set permissions on source binary first
118
- try {
119
- fs.chmodSync(sourceBinaryPath, 0o755);
120
- } catch (chmodError) {
121
- // Ignore chmod errors on Windows
122
- if (platform !== 'windows') {
123
- console.warn('Warning: Could not set permissions on source binary');
124
- }
125
- }
126
-
127
- // Copy to main binary names
128
- const mainBinaryPath = path.join(binDir, BINARY_NAME + extension);
129
- const aliasBinaryPath = path.join(binDir, 'it' + extension);
130
-
131
- // Remove existing files if they exist
132
- try {
133
- if (fs.existsSync(mainBinaryPath)) fs.unlinkSync(mainBinaryPath);
134
- if (fs.existsSync(aliasBinaryPath)) fs.unlinkSync(aliasBinaryPath);
135
- } catch (unlinkError) {
136
- // Continue if we can't remove existing files
137
- }
138
-
139
- fs.copyFileSync(sourceBinaryPath, mainBinaryPath);
140
- fs.copyFileSync(sourceBinaryPath, aliasBinaryPath);
141
-
142
- // Make executable on Unix systems
143
- if (platform !== 'windows') {
144
- try {
145
- fs.chmodSync(mainBinaryPath, 0o755);
146
- fs.chmodSync(aliasBinaryPath, 0o755);
147
- } catch (chmodError) {
148
- console.warn('Warning: Could not set executable permissions');
149
- }
150
- }
151
-
152
- log('✅ InstaTunnel CLI installed successfully!', 'green');
153
- log('', 'reset');
154
- log('🎉 Quick start:', 'yellow');
155
- log(' instatunnel 3000 # Expose port 3000', 'cyan');
156
- log(' it 3000 # Short alias', 'cyan');
157
- log(' instatunnel --help # Show all options', 'cyan');
158
- log('', 'reset');
159
-
160
- return;
161
- }
162
-
163
- // Fallback to download if pre-compiled binary not found
164
- log('📥 Downloading ' + sourceBinaryName + ' from server...', 'yellow');
165
- const downloadUrl = PRIMARY_URL + '/' + sourceBinaryName;
166
-
167
- try {
168
- await downloadFile(downloadUrl, sourceBinaryPath);
169
- } catch (err) {
170
- log('⚠️ Primary download failed, trying fallback...', 'yellow');
171
- const fallbackUrl = FALLBACK_URL + '/' + sourceBinaryName;
172
- await downloadFile(fallbackUrl, sourceBinaryPath);
173
- }
174
-
175
- // Verify download
176
- const stats = fs.statSync(sourceBinaryPath);
177
- if (stats.size < 1000000) {
178
- throw new Error('Downloaded binary appears corrupted (too small)');
179
- }
180
-
181
- // Copy to main binary names
182
- const mainBinaryPath = path.join(binDir, BINARY_NAME + extension);
183
- const aliasBinaryPath = path.join(binDir, 'it' + extension);
184
-
185
- fs.copyFileSync(sourceBinaryPath, mainBinaryPath);
186
- fs.copyFileSync(sourceBinaryPath, aliasBinaryPath);
187
-
188
- // Make executable on Unix systems
189
- if (platform !== 'windows') {
190
- fs.chmodSync(sourceBinaryPath, 0o755);
191
- fs.chmodSync(mainBinaryPath, 0o755);
192
- fs.chmodSync(aliasBinaryPath, 0o755);
193
- }
194
-
195
- log('✅ InstaTunnel CLI installed successfully!', 'green');
196
- log('', 'reset');
197
- log('🎉 Quick start:', 'yellow');
198
- log(' instatunnel 3000 # Expose port 3000', 'cyan');
199
- log(' it 3000 # Short alias', 'cyan');
200
- log(' instatunnel --help # Show all options', 'cyan');
201
- log('', 'reset');
202
-
203
- } catch (error) {
204
- throw new Error('Installation failed: ' + error.message);
94
+ log('🚀 Installing InstaTunnel CLI...', 'blue');
95
+ log(`📋 Platform: ${os.platform()}-${os.arch()}`, 'cyan');
96
+ log(`🎯 Using binary: ${binaryName}`, 'cyan');
97
+
98
+ // Check if the platform-specific binary exists
99
+ if (!fs.existsSync(sourcePath)) {
100
+ throw new Error(`Binary for your platform (${binaryName}) not found. Supported platforms: linux, macOS, Windows (x64/arm64)`);
101
+ }
102
+
103
+ // Copy the platform-specific binary to the standard name
104
+ fs.copyFileSync(sourcePath, outputPath);
105
+
106
+ // Make executable on Unix systems
107
+ if (!isWindows) {
108
+ fs.chmodSync(outputPath, 0o755);
205
109
  }
206
110
 
207
- // Test installation
111
+ // Create 'it' alias
112
+ const itPath = path.join(binDir, isWindows ? 'it.exe' : 'it');
113
+ fs.copyFileSync(outputPath, itPath);
114
+
115
+ log('✅ InstaTunnel CLI installed successfully!', 'green');
116
+ log('', 'reset');
117
+ log('🚀 Quick Start:', 'cyan');
118
+ log(' instatunnel 3000 # Expose port 3000 instantly (no setup needed!)', 'reset');
119
+ log(' it 3000 # Short alias for the same command', 'reset');
120
+ log('', 'reset');
121
+ log('💡 More examples:', 'cyan');
122
+ log(' instatunnel # Auto-detect common ports (3000, 8000, 8080)', 'reset');
123
+ log(' instatunnel 8080 --name myapp', 'reset');
124
+ log(' instatunnel --help # See all options', 'reset');
125
+ log('', 'reset');
126
+ log('🌟 Key Benefits:', 'yellow');
127
+ log(' ✓ No signup required - works instantly', 'green');
128
+ log(' ✓ 24+ hour sessions (vs ngrok\'s 2 hours)', 'green');
129
+ log(' ✓ Custom subdomains included free', 'green');
130
+ log(' ✓ 40% cheaper than ngrok', 'green');
131
+ log('', 'reset');
132
+ log('📚 Documentation: https://docs.instatunnel.my', 'yellow');
133
+
134
+ // Test installation - skip version test to avoid hanging
208
135
  try {
209
- const binaryPath = path.join(__dirname, 'bin', BINARY_NAME + (os.platform() === 'win32' ? '.exe' : ''));
210
- const stats = fs.statSync(binaryPath);
136
+ // Just verify the file exists and has content
137
+ const stats = fs.statSync(outputPath);
211
138
  if (stats.size > 1000000) { // Binary should be at least 1MB
212
- log('🔧 Installation verified! Binary size: ' + Math.round(stats.size / 1024 / 1024) + 'MB', 'green');
139
+ log(`🔧 Installation verified! Binary size: ${Math.round(stats.size / 1024 / 1024)}MB`, 'green');
213
140
  } else {
214
141
  log('⚠️ Binary seems too small, but installation completed', 'yellow');
215
142
  }
@@ -221,7 +148,30 @@ async function downloadBinary() {
221
148
  // Create uninstall script
222
149
  function createUninstallScript() {
223
150
  const uninstallPath = path.join(__dirname, 'uninstall.js');
224
- const uninstallScript = "#!/usr/bin/env node\n\nconst fs = require('fs');\nconst path = require('path');\n\nfunction cleanup() {\n const binDir = path.join(__dirname, 'bin');\n \n try {\n if (fs.existsSync(binDir)) {\n fs.rmSync(binDir, { recursive: true, force: true });\n }\n console.log('✅ InstaTunnel CLI uninstalled successfully!');\n } catch (error) {\n console.warn('⚠️ Some cleanup may be incomplete:', error.message);\n }\n}\n\nif (require.main === module) {\n cleanup();\n}\n\nmodule.exports = { cleanup };\n";
151
+ const uninstallScript = `#!/usr/bin/env node
152
+
153
+ const fs = require('fs');
154
+ const path = require('path');
155
+
156
+ function cleanup() {
157
+ const binDir = path.join(__dirname, 'bin');
158
+
159
+ try {
160
+ if (fs.existsSync(binDir)) {
161
+ fs.rmSync(binDir, { recursive: true, force: true });
162
+ }
163
+ console.log('✅ InstaTunnel CLI uninstalled successfully!');
164
+ } catch (error) {
165
+ console.warn('⚠️ Some cleanup may be incomplete:', error.message);
166
+ }
167
+ }
168
+
169
+ if (require.main === module) {
170
+ cleanup();
171
+ }
172
+
173
+ module.exports = { cleanup };
174
+ `;
225
175
 
226
176
  fs.writeFileSync(uninstallPath, uninstallScript);
227
177
  }
@@ -229,23 +179,57 @@ function createUninstallScript() {
229
179
  // Create test script
230
180
  function createTestScript() {
231
181
  const testPath = path.join(__dirname, 'test.js');
232
- const extension = os.platform() === 'win32' ? '.exe' : '';
233
- const testScript = "#!/usr/bin/env node\n\nconst { execSync } = require('child_process');\nconst path = require('path');\nconst os = require('os');\n\nfunction test() {\n const binDir = path.join(__dirname, 'bin');\n const extension = os.platform() === 'win32' ? '.exe' : '';\n const instatunnelPath = path.join(binDir, 'instatunnel' + extension);\n const itPath = path.join(binDir, 'it' + extension);\n \n try {\n // Test main command - execute binary directly, not with node\n const helpOutput = execSync('\"' + instatunnelPath + '\" --help', { encoding: 'utf8', timeout: 5000 });\n console.log('✅ instatunnel command works');\n \n // Test alias - execute binary directly, not with node\n const itHelpOutput = execSync('\"' + itPath + '\" --help', { encoding: 'utf8', timeout: 5000 });\n console.log('✅ it alias works');\n \n console.log('✅ All tests passed!');\n return true;\n } catch (error) {\n console.error('❌ Test failed:', error.message);\n return false;\n }\n}\n\nif (require.main === module) {\n const success = test();\n process.exit(success ? 0 : 1);\n}\n\nmodule.exports = { test };\n";
182
+ const testScript = `#!/usr/bin/env node
183
+
184
+ const { execSync } = require('child_process');
185
+ const path = require('path');
186
+ const os = require('os');
187
+
188
+ function test() {
189
+ const binDir = path.join(__dirname, 'bin');
190
+ const isWindows = os.platform() === 'win32';
191
+ const instatunnelPath = path.join(binDir, isWindows ? 'instatunnel.exe' : 'instatunnel');
192
+ const itPath = path.join(binDir, isWindows ? 'it.exe' : 'it');
193
+
194
+ try {
195
+ // Test main command
196
+ const helpOutput = execSync(\`"\${instatunnelPath}" --help\`, { encoding: 'utf8', timeout: 5000 });
197
+ console.log('✅ instatunnel command works');
198
+
199
+ // Test alias
200
+ const itHelpOutput = execSync(\`"\${itPath}" --help\`, { encoding: 'utf8', timeout: 5000 });
201
+ console.log('✅ it alias works');
202
+
203
+ console.log('✅ All tests passed!');
204
+ return true;
205
+ } catch (error) {
206
+ console.error('❌ Test failed:', error.message);
207
+ return false;
208
+ }
209
+ }
210
+
211
+ if (require.main === module) {
212
+ const success = test();
213
+ process.exit(success ? 0 : 1);
214
+ }
215
+
216
+ module.exports = { test };
217
+ `;
234
218
 
235
219
  fs.writeFileSync(testPath, testScript);
236
220
  }
237
221
 
238
222
  if (require.main === module) {
239
- downloadBinary()
223
+ setupBinary()
240
224
  .then(() => {
241
225
  createUninstallScript();
242
226
  createTestScript();
243
227
  })
244
228
  .catch((err) => {
245
- log('❌ Installation failed: ' + err.message, 'red');
229
+ log(`❌ Installation failed: ${err.message}`, 'red');
246
230
  log('', 'reset');
247
231
  log('🔧 Troubleshooting:', 'yellow');
248
- log(' • Check your internet connection', 'reset');
232
+ log(' • Your platform may not be supported yet', 'reset');
249
233
  log(' • Try running: npm install -g instatunnel --verbose', 'reset');
250
234
  log(' • Report issues: https://github.com/instatunnel/cli/issues', 'reset');
251
235
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instatunnel",
3
- "version": "1.0.28",
3
+ "version": "1.0.30",
4
4
  "description": "Expose your localhost to the internet instantly - the ngrok alternative that's 40% cheaper with superior UX",
5
5
  "main": "install.js",
6
6
  "bin": {