devtunnel-cli 3.0.8 → 3.0.9
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 +275 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devtunnel-cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.9",
|
|
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,127 @@ 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
|
+
// Try to detect port
|
|
140
|
+
let detectedPort = detectPortFromPackage(packagePath);
|
|
141
|
+
|
|
142
|
+
// If no port detected, check running servers
|
|
143
|
+
if (!detectedPort) {
|
|
144
|
+
const runningPorts = await detectRunningDevServer();
|
|
145
|
+
if (runningPorts.length > 0) {
|
|
146
|
+
detectedPort = runningPorts[0]; // Use first detected port
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
path: currentDir,
|
|
152
|
+
name: projectName,
|
|
153
|
+
port: detectedPort
|
|
154
|
+
};
|
|
155
|
+
} catch (err) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
38
160
|
// ASCII Logo - Compatible with all OS and terminals
|
|
39
161
|
function showLogo() {
|
|
40
162
|
console.log("");
|
|
@@ -61,7 +183,7 @@ async function main() {
|
|
|
61
183
|
// Show ASCII logo
|
|
62
184
|
showLogo();
|
|
63
185
|
|
|
64
|
-
console.log("DevTunnel v3.0.
|
|
186
|
+
console.log("DevTunnel v3.0.9");
|
|
65
187
|
console.log("Share your local dev servers worldwide");
|
|
66
188
|
console.log("");
|
|
67
189
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
@@ -147,36 +269,162 @@ async function main() {
|
|
|
147
269
|
}
|
|
148
270
|
console.log("");
|
|
149
271
|
|
|
150
|
-
// Step 4:
|
|
151
|
-
console.log("[4/4]
|
|
152
|
-
console.log("Opening folder picker...");
|
|
153
|
-
console.log("");
|
|
272
|
+
// Step 4: Auto-detect or select project
|
|
273
|
+
console.log("[4/4] Detecting project...");
|
|
154
274
|
|
|
155
|
-
|
|
275
|
+
let projectPath, projectName, devPort;
|
|
156
276
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
277
|
+
// Try to auto-detect project in current directory
|
|
278
|
+
const autoDetected = await autoDetectProject();
|
|
161
279
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
280
|
+
if (autoDetected && autoDetected.port) {
|
|
281
|
+
// Auto-detected project with port
|
|
282
|
+
projectPath = autoDetected.path;
|
|
283
|
+
projectName = autoDetected.name;
|
|
284
|
+
devPort = autoDetected.port;
|
|
285
|
+
|
|
286
|
+
console.log(`Detected project: ${projectName}`);
|
|
287
|
+
console.log(`Detected port: ${devPort}`);
|
|
288
|
+
console.log(`Using current directory: ${projectPath}`);
|
|
289
|
+
console.log("");
|
|
290
|
+
|
|
291
|
+
// Confirm with user
|
|
292
|
+
const confirm = await prompts({
|
|
293
|
+
type: "confirm",
|
|
294
|
+
name: "value",
|
|
295
|
+
message: "Use detected project?",
|
|
296
|
+
initial: true
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (!confirm.value) {
|
|
300
|
+
// User wants to select manually
|
|
301
|
+
console.log("");
|
|
302
|
+
console.log("Selecting project manually...");
|
|
303
|
+
console.log("");
|
|
304
|
+
|
|
305
|
+
const selectedPath = await selectFolder();
|
|
306
|
+
if (!selectedPath || selectedPath.length === 0) {
|
|
307
|
+
console.log("ERROR: No folder selected");
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
projectPath = selectedPath;
|
|
312
|
+
projectName = basename(selectedPath);
|
|
313
|
+
|
|
314
|
+
// Try to detect port for selected project
|
|
315
|
+
const selectedPackagePath = join(selectedPath, 'package.json');
|
|
316
|
+
const detectedPort = detectPortFromPackage(selectedPackagePath);
|
|
317
|
+
|
|
318
|
+
const portResponse = await prompts({
|
|
319
|
+
type: "number",
|
|
320
|
+
name: "port",
|
|
321
|
+
message: "Enter your dev server port:",
|
|
322
|
+
initial: detectedPort || 5173
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
if (!portResponse.port) {
|
|
326
|
+
console.log("ERROR: No port entered");
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
devPort = portResponse.port;
|
|
331
|
+
}
|
|
332
|
+
} else if (autoDetected && !autoDetected.port) {
|
|
333
|
+
// Project detected but no port
|
|
334
|
+
projectPath = autoDetected.path;
|
|
335
|
+
projectName = autoDetected.name;
|
|
336
|
+
|
|
337
|
+
console.log(`Detected project: ${projectName}`);
|
|
338
|
+
console.log(`Using current directory: ${projectPath}`);
|
|
339
|
+
console.log("Checking for running dev servers...");
|
|
340
|
+
|
|
341
|
+
const runningPorts = await detectRunningDevServer();
|
|
342
|
+
|
|
343
|
+
if (runningPorts.length > 0) {
|
|
344
|
+
console.log(`Found ${runningPorts.length} running dev server(s) on port(s): ${runningPorts.join(', ')}`);
|
|
345
|
+
|
|
346
|
+
if (runningPorts.length === 1) {
|
|
347
|
+
devPort = runningPorts[0];
|
|
348
|
+
console.log(`Using port: ${devPort}`);
|
|
349
|
+
} else {
|
|
350
|
+
// Multiple ports detected, let user choose
|
|
351
|
+
const portResponse = await prompts({
|
|
352
|
+
type: "select",
|
|
353
|
+
name: "port",
|
|
354
|
+
message: "Select port:",
|
|
355
|
+
choices: runningPorts.map(p => ({ title: `Port ${p}`, value: p }))
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
if (!portResponse.port) {
|
|
359
|
+
console.log("ERROR: No port selected");
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
devPort = portResponse.port;
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
// No running server, ask for port
|
|
367
|
+
const portResponse = await prompts({
|
|
368
|
+
type: "number",
|
|
369
|
+
name: "port",
|
|
370
|
+
message: "Enter your dev server port:",
|
|
371
|
+
initial: 5173
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
if (!portResponse.port) {
|
|
375
|
+
console.log("ERROR: No port entered");
|
|
376
|
+
process.exit(1);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
devPort = portResponse.port;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
console.log("");
|
|
383
|
+
} else {
|
|
384
|
+
// No auto-detection, use folder picker
|
|
385
|
+
console.log("No project detected in current directory");
|
|
386
|
+
console.log("Opening folder picker...");
|
|
387
|
+
console.log("");
|
|
388
|
+
|
|
389
|
+
projectPath = await selectFolder();
|
|
390
|
+
|
|
391
|
+
if (!projectPath || projectPath.length === 0) {
|
|
392
|
+
console.log("ERROR: No folder selected");
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
projectName = basename(projectPath);
|
|
397
|
+
console.log(`Selected: ${projectPath}`);
|
|
398
|
+
console.log("");
|
|
399
|
+
|
|
400
|
+
// Try to detect port for selected project
|
|
401
|
+
const selectedPackagePath = join(projectPath, 'package.json');
|
|
402
|
+
const detectedPort = detectPortFromPackage(selectedPackagePath);
|
|
403
|
+
|
|
404
|
+
// Check for running servers
|
|
405
|
+
const runningPorts = await detectRunningDevServer();
|
|
406
|
+
|
|
407
|
+
let initialPort = detectedPort || 5173;
|
|
408
|
+
if (runningPorts.length > 0 && !detectedPort) {
|
|
409
|
+
initialPort = runningPorts[0];
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const portResponse = await prompts({
|
|
413
|
+
type: "number",
|
|
414
|
+
name: "port",
|
|
415
|
+
message: "Enter your dev server port:",
|
|
416
|
+
initial: initialPort
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
if (!portResponse.port) {
|
|
420
|
+
console.log("ERROR: No port entered");
|
|
421
|
+
process.exit(1);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
devPort = portResponse.port;
|
|
177
425
|
}
|
|
178
426
|
|
|
179
|
-
|
|
427
|
+
console.log("");
|
|
180
428
|
const proxyPort = devPort + 1000; // Use port 1000 higher for proxy
|
|
181
429
|
|
|
182
430
|
console.log("");
|