devtunnel-cli 3.0.8 → 3.0.10
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/package.json +1 -1
- package/src/core/start.js +314 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devtunnel-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.10",
|
|
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",
|
package/src/core/start.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
-
import { existsSync } from "fs";
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
3
|
import { join, dirname, basename } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
+
import http from "http";
|
|
5
6
|
import prompts from "prompts";
|
|
6
7
|
import { selectFolder } from "../utils/folder-picker.js";
|
|
7
8
|
|
|
@@ -35,6 +36,128 @@ async function commandExists(command) {
|
|
|
35
36
|
return result.code === 0;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
// Check if a port is in use (dev server running)
|
|
40
|
+
function checkPortInUse(port) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const server = http.createServer();
|
|
43
|
+
|
|
44
|
+
server.once('error', (err) => {
|
|
45
|
+
// Port is in use
|
|
46
|
+
if (err.code === 'EADDRINUSE') {
|
|
47
|
+
resolve(true);
|
|
48
|
+
} else {
|
|
49
|
+
resolve(false);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
server.listen(port, () => {
|
|
54
|
+
// Port is available (not in use)
|
|
55
|
+
server.once('close', () => resolve(false));
|
|
56
|
+
server.close();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Detect port from package.json
|
|
62
|
+
function detectPortFromPackage(packagePath) {
|
|
63
|
+
try {
|
|
64
|
+
if (!existsSync(packagePath)) return null;
|
|
65
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
66
|
+
const scripts = packageJson.scripts || {};
|
|
67
|
+
|
|
68
|
+
// Check for common dev commands
|
|
69
|
+
const devScript = scripts.dev || scripts.start || scripts.serve;
|
|
70
|
+
if (!devScript) return null;
|
|
71
|
+
|
|
72
|
+
// Try to extract port from script
|
|
73
|
+
const portMatch = devScript.match(/--port\s+(\d+)|:(\d+)|port[=:](\d+)/i);
|
|
74
|
+
if (portMatch) {
|
|
75
|
+
return parseInt(portMatch[1] || portMatch[2] || portMatch[3]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Default ports based on framework
|
|
79
|
+
if (devScript.includes('vite')) return 5173;
|
|
80
|
+
if (devScript.includes('next')) return 3000;
|
|
81
|
+
if (devScript.includes('react-scripts')) return 3000;
|
|
82
|
+
if (devScript.includes('webpack')) return 8080;
|
|
83
|
+
if (devScript.includes('express')) return 3000;
|
|
84
|
+
|
|
85
|
+
return null;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Check common ports for running dev servers
|
|
92
|
+
async function detectRunningDevServer() {
|
|
93
|
+
const commonPorts = [3000, 5173, 8080, 5000, 4000, 8000, 3001, 5174];
|
|
94
|
+
const detected = [];
|
|
95
|
+
|
|
96
|
+
for (const port of commonPorts) {
|
|
97
|
+
const inUse = await checkPortInUse(port);
|
|
98
|
+
if (inUse) {
|
|
99
|
+
// Try to verify it's actually a dev server by making a request
|
|
100
|
+
try {
|
|
101
|
+
const response = await new Promise((resolve) => {
|
|
102
|
+
const req = http.get(`http://localhost:${port}`, { timeout: 2000 }, (res) => {
|
|
103
|
+
resolve(res.statusCode);
|
|
104
|
+
});
|
|
105
|
+
req.on('error', () => resolve(null));
|
|
106
|
+
req.on('timeout', () => {
|
|
107
|
+
req.destroy();
|
|
108
|
+
resolve(null);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// If we get any HTTP response, it's likely a dev server
|
|
112
|
+
if (response !== null) {
|
|
113
|
+
detected.push(port);
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
// Port is in use, add it anyway (might be a dev server)
|
|
117
|
+
detected.push(port);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return detected;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Auto-detect project in current directory
|
|
126
|
+
async function autoDetectProject() {
|
|
127
|
+
const currentDir = process.cwd();
|
|
128
|
+
const packagePath = join(currentDir, 'package.json');
|
|
129
|
+
|
|
130
|
+
// Check if package.json exists
|
|
131
|
+
if (!existsSync(packagePath)) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
137
|
+
const projectName = packageJson.name || basename(currentDir);
|
|
138
|
+
|
|
139
|
+
// FIRST: Check for running dev servers (priority)
|
|
140
|
+
const runningPorts = await detectRunningDevServer();
|
|
141
|
+
let detectedPort = null;
|
|
142
|
+
|
|
143
|
+
if (runningPorts.length > 0) {
|
|
144
|
+
// Use running server port (most accurate)
|
|
145
|
+
detectedPort = runningPorts[0];
|
|
146
|
+
} else {
|
|
147
|
+
// Fallback: Try to detect port from package.json
|
|
148
|
+
detectedPort = detectPortFromPackage(packagePath);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
path: currentDir,
|
|
153
|
+
name: projectName,
|
|
154
|
+
port: detectedPort
|
|
155
|
+
};
|
|
156
|
+
} catch (err) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
38
161
|
// ASCII Logo - Compatible with all OS and terminals
|
|
39
162
|
function showLogo() {
|
|
40
163
|
console.log("");
|
|
@@ -61,7 +184,7 @@ async function main() {
|
|
|
61
184
|
// Show ASCII logo
|
|
62
185
|
showLogo();
|
|
63
186
|
|
|
64
|
-
console.log("DevTunnel v3.0.
|
|
187
|
+
console.log("DevTunnel v3.0.10");
|
|
65
188
|
console.log("Share your local dev servers worldwide");
|
|
66
189
|
console.log("");
|
|
67
190
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
@@ -147,36 +270,200 @@ async function main() {
|
|
|
147
270
|
}
|
|
148
271
|
console.log("");
|
|
149
272
|
|
|
150
|
-
// Step 4:
|
|
151
|
-
console.log("[4/4]
|
|
152
|
-
console.log("Opening folder picker...");
|
|
153
|
-
console.log("");
|
|
273
|
+
// Step 4: Auto-detect or select project
|
|
274
|
+
console.log("[4/4] Detecting project...");
|
|
154
275
|
|
|
155
|
-
|
|
276
|
+
let projectPath, projectName, devPort;
|
|
156
277
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const projectName = basename(projectPath);
|
|
163
|
-
console.log(`Selected: ${projectPath}`);
|
|
164
|
-
console.log("");
|
|
165
|
-
|
|
166
|
-
// Get port
|
|
167
|
-
const portResponse = await prompts({
|
|
168
|
-
type: "number",
|
|
169
|
-
name: "port",
|
|
170
|
-
message: "Enter your dev server port:",
|
|
171
|
-
initial: 5173
|
|
172
|
-
});
|
|
278
|
+
// Try to auto-detect project in current directory
|
|
279
|
+
const autoDetected = await autoDetectProject();
|
|
173
280
|
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
281
|
+
if (autoDetected && autoDetected.port) {
|
|
282
|
+
// Auto-detected project with port
|
|
283
|
+
projectPath = autoDetected.path;
|
|
284
|
+
projectName = autoDetected.name;
|
|
285
|
+
|
|
286
|
+
// Double-check: verify the port is actually in use
|
|
287
|
+
const portInUse = await checkPortInUse(autoDetected.port);
|
|
288
|
+
|
|
289
|
+
if (!portInUse) {
|
|
290
|
+
// Detected port is not actually running, check for other running servers
|
|
291
|
+
console.log(`Detected port ${autoDetected.port} from package.json, but no server running on that port`);
|
|
292
|
+
console.log("Checking for running dev servers...");
|
|
293
|
+
|
|
294
|
+
const runningPorts = await detectRunningDevServer();
|
|
295
|
+
if (runningPorts.length > 0) {
|
|
296
|
+
if (runningPorts.length === 1) {
|
|
297
|
+
devPort = runningPorts[0];
|
|
298
|
+
console.log(`Found running dev server on port: ${devPort}`);
|
|
299
|
+
} else {
|
|
300
|
+
console.log(`Found ${runningPorts.length} running dev server(s) on port(s): ${runningPorts.join(', ')}`);
|
|
301
|
+
const portResponse = await prompts({
|
|
302
|
+
type: "select",
|
|
303
|
+
name: "port",
|
|
304
|
+
message: "Select port:",
|
|
305
|
+
choices: runningPorts.map(p => ({ title: `Port ${p}`, value: p }))
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (!portResponse.port) {
|
|
309
|
+
console.log("ERROR: No port selected");
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
devPort = portResponse.port;
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
// No running servers, use detected port (user might start it later)
|
|
317
|
+
devPort = autoDetected.port;
|
|
318
|
+
console.log(`Using detected port: ${devPort} (make sure dev server is running)`);
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
// Port is in use, use it
|
|
322
|
+
devPort = autoDetected.port;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
console.log(`Detected project: ${projectName}`);
|
|
326
|
+
console.log(`Using port: ${devPort}`);
|
|
327
|
+
console.log(`Using current directory: ${projectPath}`);
|
|
328
|
+
console.log("");
|
|
329
|
+
|
|
330
|
+
// Confirm with user
|
|
331
|
+
const confirm = await prompts({
|
|
332
|
+
type: "confirm",
|
|
333
|
+
name: "value",
|
|
334
|
+
message: "Use detected project?",
|
|
335
|
+
initial: true
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (!confirm.value) {
|
|
339
|
+
// User wants to select manually
|
|
340
|
+
console.log("");
|
|
341
|
+
console.log("Selecting project manually...");
|
|
342
|
+
console.log("");
|
|
343
|
+
|
|
344
|
+
const selectedPath = await selectFolder();
|
|
345
|
+
if (!selectedPath || selectedPath.length === 0) {
|
|
346
|
+
console.log("ERROR: No folder selected");
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
projectPath = selectedPath;
|
|
351
|
+
projectName = basename(selectedPath);
|
|
352
|
+
|
|
353
|
+
// Try to detect port for selected project
|
|
354
|
+
const selectedPackagePath = join(selectedPath, 'package.json');
|
|
355
|
+
const detectedPort = detectPortFromPackage(selectedPackagePath);
|
|
356
|
+
|
|
357
|
+
const portResponse = await prompts({
|
|
358
|
+
type: "number",
|
|
359
|
+
name: "port",
|
|
360
|
+
message: "Enter your dev server port:",
|
|
361
|
+
initial: detectedPort || 5173
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
if (!portResponse.port) {
|
|
365
|
+
console.log("ERROR: No port entered");
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
devPort = portResponse.port;
|
|
370
|
+
}
|
|
371
|
+
} else if (autoDetected && !autoDetected.port) {
|
|
372
|
+
// Project detected but no port
|
|
373
|
+
projectPath = autoDetected.path;
|
|
374
|
+
projectName = autoDetected.name;
|
|
375
|
+
|
|
376
|
+
console.log(`Detected project: ${projectName}`);
|
|
377
|
+
console.log(`Using current directory: ${projectPath}`);
|
|
378
|
+
console.log("Checking for running dev servers...");
|
|
379
|
+
|
|
380
|
+
const runningPorts = await detectRunningDevServer();
|
|
381
|
+
|
|
382
|
+
if (runningPorts.length > 0) {
|
|
383
|
+
console.log(`Found ${runningPorts.length} running dev server(s) on port(s): ${runningPorts.join(', ')}`);
|
|
384
|
+
|
|
385
|
+
if (runningPorts.length === 1) {
|
|
386
|
+
devPort = runningPorts[0];
|
|
387
|
+
console.log(`Using port: ${devPort}`);
|
|
388
|
+
} else {
|
|
389
|
+
// Multiple ports detected, let user choose
|
|
390
|
+
const portResponse = await prompts({
|
|
391
|
+
type: "select",
|
|
392
|
+
name: "port",
|
|
393
|
+
message: "Select port:",
|
|
394
|
+
choices: runningPorts.map(p => ({ title: `Port ${p}`, value: p }))
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
if (!portResponse.port) {
|
|
398
|
+
console.log("ERROR: No port selected");
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
devPort = portResponse.port;
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
// No running server, ask for port
|
|
406
|
+
const portResponse = await prompts({
|
|
407
|
+
type: "number",
|
|
408
|
+
name: "port",
|
|
409
|
+
message: "Enter your dev server port:",
|
|
410
|
+
initial: 5173
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
if (!portResponse.port) {
|
|
414
|
+
console.log("ERROR: No port entered");
|
|
415
|
+
process.exit(1);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
devPort = portResponse.port;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
console.log("");
|
|
422
|
+
} else {
|
|
423
|
+
// No auto-detection, use folder picker
|
|
424
|
+
console.log("No project detected in current directory");
|
|
425
|
+
console.log("Opening folder picker...");
|
|
426
|
+
console.log("");
|
|
427
|
+
|
|
428
|
+
projectPath = await selectFolder();
|
|
429
|
+
|
|
430
|
+
if (!projectPath || projectPath.length === 0) {
|
|
431
|
+
console.log("ERROR: No folder selected");
|
|
432
|
+
process.exit(1);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
projectName = basename(projectPath);
|
|
436
|
+
console.log(`Selected: ${projectPath}`);
|
|
437
|
+
console.log("");
|
|
438
|
+
|
|
439
|
+
// Try to detect port for selected project
|
|
440
|
+
const selectedPackagePath = join(projectPath, 'package.json');
|
|
441
|
+
const detectedPort = detectPortFromPackage(selectedPackagePath);
|
|
442
|
+
|
|
443
|
+
// Check for running servers
|
|
444
|
+
const runningPorts = await detectRunningDevServer();
|
|
445
|
+
|
|
446
|
+
let initialPort = detectedPort || 5173;
|
|
447
|
+
if (runningPorts.length > 0 && !detectedPort) {
|
|
448
|
+
initialPort = runningPorts[0];
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const portResponse = await prompts({
|
|
452
|
+
type: "number",
|
|
453
|
+
name: "port",
|
|
454
|
+
message: "Enter your dev server port:",
|
|
455
|
+
initial: initialPort
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
if (!portResponse.port) {
|
|
459
|
+
console.log("ERROR: No port entered");
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
devPort = portResponse.port;
|
|
177
464
|
}
|
|
178
465
|
|
|
179
|
-
|
|
466
|
+
console.log("");
|
|
180
467
|
const proxyPort = devPort + 1000; // Use port 1000 higher for proxy
|
|
181
468
|
|
|
182
469
|
console.log("");
|