devtunnel-cli 3.0.12 → 3.0.14

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 CHANGED
@@ -106,7 +106,7 @@ MIT License - see [LICENSE](docs/LICENSE)
106
106
 
107
107
  ---
108
108
 
109
- **Version 3.0.11** | Made with ❤️ for developers worldwide
109
+ **Version 3.0.13** | Made with ❤️ for developers worldwide
110
110
 
111
111
  ---
112
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devtunnel-cli",
3
- "version": "3.0.12",
3
+ "version": "3.0.14",
4
4
  "type": "module",
5
5
  "description": "DevTunnel - Share local dev servers worldwide. Zero configuration tunnel for any framework. Install via npm: npm install -g devtunnel-cli. Works with Vite, React, Next.js, Express, NestJS and more.",
6
6
  "main": "src/core/start.js",
@@ -1,10 +1,12 @@
1
- import { spawn } from 'child_process';
1
+ import { spawn, exec } from 'child_process';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import https from 'https';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { dirname } from 'path';
7
+ import { promisify } from 'util';
7
8
 
9
+ const execAsync = promisify(exec);
8
10
  const __filename = fileURLToPath(import.meta.url);
9
11
  const __dirname = dirname(__filename);
10
12
 
@@ -60,10 +62,35 @@ function safeUnlink(filePath) {
60
62
  }
61
63
  } catch (err) {
62
64
  // Ignore permission errors - file might be locked or in use
63
- // Will be cleaned up later or on next run
64
65
  }
65
66
  }
66
67
 
68
+ async function isAdmin() {
69
+ if (process.platform !== 'win32') {
70
+ return process.getuid && process.getuid() === 0;
71
+ }
72
+
73
+ try {
74
+ const { stdout } = await execAsync('net session');
75
+ return stdout.length > 0;
76
+ } catch {
77
+ return false;
78
+ }
79
+ }
80
+
81
+ function showPermissionSolutions(dirPath) {
82
+ console.log('\n💡 Solutions:');
83
+ if (process.platform === 'win32') {
84
+ console.log(' 1. Run terminal as Administrator (Right-click → Run as administrator)');
85
+ console.log(' 2. DevTunnel will automatically request admin privileges if needed');
86
+ } else {
87
+ console.log(' 1. Run with sudo: sudo npm install -g devtunnel-cli');
88
+ }
89
+ console.log(' 2. Check if antivirus is blocking file writes');
90
+ console.log(' 3. Check folder permissions for:', dirPath);
91
+ console.log(' 4. Try installing manually: https://github.com/cloudflare/cloudflared/releases\n');
92
+ }
93
+
67
94
  function downloadFile(url, dest, retryCount = 0) {
68
95
  return new Promise((resolve, reject) => {
69
96
  const dir = path.dirname(dest);
@@ -220,12 +247,45 @@ async function downloadWithRetry(urls, dest, maxRetries = 3) {
220
247
 
221
248
  if (err.message.includes('Permission denied') || err.message.includes('EPERM') || err.message.includes('EACCES')) {
222
249
  console.log(`\n❌ Permission Error: ${err.message}`);
223
- console.log('\n💡 Solutions:');
224
- console.log(' 1. Run terminal as Administrator (Right-click Run as administrator)');
225
- console.log(' 2. Check if antivirus is blocking file writes');
226
- console.log(' 3. Check folder permissions for:', path.dirname(dest));
227
- console.log(' 4. Try installing manually: https://github.com/cloudflare/cloudflared/releases\n');
228
- throw err; // Don't retry permission errors
250
+
251
+ if (process.platform === 'win32' && retry === 0) {
252
+ const admin = await isAdmin();
253
+ if (!admin) {
254
+ console.log('\n🔐 Attempting to request administrator privileges...');
255
+ console.log(' Please click "Yes" on the UAC prompt\n');
256
+
257
+ try {
258
+ const nodePath = process.execPath;
259
+ const scriptPath = process.argv[1];
260
+ const proc = spawn('powershell', [
261
+ '-NoProfile',
262
+ '-NonInteractive',
263
+ '-ExecutionPolicy', 'Bypass',
264
+ '-Command', `Start-Process -FilePath "${nodePath}" -ArgumentList "${scriptPath}" -Verb RunAs -Wait`
265
+ ], {
266
+ stdio: 'inherit',
267
+ shell: false
268
+ });
269
+
270
+ proc.on('close', () => {
271
+ process.exit(0);
272
+ });
273
+
274
+ proc.on('error', () => {
275
+ console.log('\n⚠️ Could not elevate privileges automatically');
276
+ showPermissionSolutions(path.dirname(dest));
277
+ });
278
+
279
+ return false;
280
+ } catch {
281
+ showPermissionSolutions(path.dirname(dest));
282
+ throw err;
283
+ }
284
+ }
285
+ }
286
+
287
+ showPermissionSolutions(path.dirname(dest));
288
+ throw err;
229
289
  } else if (err.message.includes('ENOTFOUND') || err.message.includes('ECONNREFUSED')) {
230
290
  console.log(`\n❌ Network error: ${err.message}`);
231
291
  } else if (err.message.includes('timeout')) {
@@ -345,12 +405,7 @@ export async function setupCloudflared() {
345
405
  console.error(`Reason: ${err.message}\n`);
346
406
 
347
407
  if (err.message.includes('Permission denied') || err.message.includes('EPERM') || err.message.includes('EACCES')) {
348
- console.log('💡 Permission Error Solutions:');
349
- console.log(' 1. Run terminal as Administrator (Right-click → Run as administrator)');
350
- console.log(' 2. Check antivirus is not blocking file writes');
351
- console.log(' 3. Check folder permissions for:', path.dirname(binaryPath));
352
- console.log(' 4. Try installing Cloudflare manually:');
353
- console.log(' https://github.com/cloudflare/cloudflared/releases\n');
408
+ showPermissionSolutions(path.dirname(binaryPath));
354
409
  } else {
355
410
  console.log('💡 Troubleshooting:');
356
411
  console.log(' 1. Check internet connection');
package/src/core/start.js CHANGED
@@ -183,7 +183,7 @@ async function main() {
183
183
  // Show ASCII logo
184
184
  showLogo();
185
185
 
186
- console.log("DevTunnel v3.0.12");
186
+ console.log("DevTunnel v3.0.13");
187
187
  console.log("Share your local dev servers worldwide");
188
188
  console.log("");
189
189
  console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");