genbox 1.0.96 → 1.0.98
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/dist/scanner/index.js +117 -11
- package/package.json +1 -1
package/dist/scanner/index.js
CHANGED
|
@@ -66,6 +66,8 @@ class ProjectScanner {
|
|
|
66
66
|
const apps = await this.discoverApps(root, structure, compose, options.exclude);
|
|
67
67
|
// Layer 5.5: Apply framework detection to apps (ports, commands, etc.)
|
|
68
68
|
await this.applyFrameworkDefaults(root, apps, frameworks);
|
|
69
|
+
// Layer 5.6: Ensure unique ports for all apps (avoid collisions)
|
|
70
|
+
this.ensureUniquePorts(apps);
|
|
69
71
|
// Layer 6: Analyze environment variables (skip if option set)
|
|
70
72
|
const envAnalysis = options.skipEnv
|
|
71
73
|
? { required: [], optional: [], secrets: [], references: [], sources: [] }
|
|
@@ -168,20 +170,41 @@ class ProjectScanner {
|
|
|
168
170
|
const hasStartScript = !!(pkg.scripts?.start || pkg.scripts?.dev || pkg.scripts?.serve);
|
|
169
171
|
const type = this.inferAppTypeFromPackage(entry.name, pkg, hasStartScript);
|
|
170
172
|
// Try to detect framework
|
|
173
|
+
// Priority: fullstack frameworks > meta-frameworks > dev servers > UI libraries
|
|
171
174
|
let framework;
|
|
172
175
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
176
|
+
// 1. Fullstack/meta-frameworks (most specific)
|
|
173
177
|
if (deps['next'])
|
|
174
178
|
framework = 'nextjs';
|
|
179
|
+
else if (deps['nuxt'])
|
|
180
|
+
framework = 'nuxt';
|
|
181
|
+
else if (deps['@remix-run/react'])
|
|
182
|
+
framework = 'remix';
|
|
183
|
+
else if (deps['astro'])
|
|
184
|
+
framework = 'astro';
|
|
185
|
+
else if (deps['@sveltejs/kit'])
|
|
186
|
+
framework = 'sveltekit';
|
|
187
|
+
// 2. Backend frameworks
|
|
175
188
|
else if (deps['@nestjs/core'])
|
|
176
189
|
framework = 'nestjs';
|
|
190
|
+
else if (deps['fastify'])
|
|
191
|
+
framework = 'fastify';
|
|
192
|
+
else if (deps['express'])
|
|
193
|
+
framework = 'express';
|
|
194
|
+
else if (deps['hono'])
|
|
195
|
+
framework = 'hono';
|
|
196
|
+
// 3. Dev servers (determines port)
|
|
197
|
+
else if (deps['vite'])
|
|
198
|
+
framework = 'vite';
|
|
199
|
+
// 4. UI libraries (least specific - use dev server port if available)
|
|
177
200
|
else if (deps['react-admin'])
|
|
178
|
-
framework = 'react-admin
|
|
201
|
+
framework = 'vite'; // react-admin uses vite
|
|
179
202
|
else if (deps['react'])
|
|
180
203
|
framework = 'react';
|
|
181
204
|
else if (deps['vue'])
|
|
182
205
|
framework = 'vue';
|
|
183
|
-
else if (deps['
|
|
184
|
-
framework = '
|
|
206
|
+
else if (deps['svelte'])
|
|
207
|
+
framework = 'svelte';
|
|
185
208
|
// Try to detect port from package.json scripts
|
|
186
209
|
let port;
|
|
187
210
|
const devScript = pkg.scripts?.dev || pkg.scripts?.start || '';
|
|
@@ -368,18 +391,101 @@ class ProjectScanner {
|
|
|
368
391
|
if (!app.framework) {
|
|
369
392
|
app.framework = appFramework.name;
|
|
370
393
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
394
|
+
}
|
|
395
|
+
// Priority 1: Detect port from config files (vite.config.ts, etc.)
|
|
396
|
+
if (!app.port) {
|
|
397
|
+
const configPort = this.detectPortFromConfig(appPath);
|
|
398
|
+
if (configPort) {
|
|
399
|
+
app.port = configPort;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// Priority 2: Use framework default from detector
|
|
403
|
+
if (!app.port && appFramework?.defaultPort) {
|
|
404
|
+
app.port = appFramework.defaultPort;
|
|
405
|
+
}
|
|
406
|
+
// Priority 3: Use hardcoded framework default as last resort
|
|
407
|
+
if (!app.port && app.framework) {
|
|
408
|
+
app.port = this.getDefaultPortForFramework(app.framework);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Detect port from config files (vite.config.ts, next.config.js, etc.)
|
|
414
|
+
*/
|
|
415
|
+
detectPortFromConfig(appPath) {
|
|
416
|
+
const fs = require('fs');
|
|
417
|
+
const pathModule = require('path');
|
|
418
|
+
// Try vite.config.ts/js
|
|
419
|
+
for (const configFile of ['vite.config.ts', 'vite.config.js', 'vite.config.mts', 'vite.config.mjs']) {
|
|
420
|
+
const configPath = pathModule.join(appPath, configFile);
|
|
421
|
+
if (fs.existsSync(configPath)) {
|
|
422
|
+
try {
|
|
423
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
424
|
+
// Match server.port or server: { port: XXXX }
|
|
425
|
+
const portMatch = content.match(/server\s*:\s*\{[^}]*port\s*:\s*(\d+)/s) ||
|
|
426
|
+
content.match(/port\s*:\s*(\d+)/);
|
|
427
|
+
if (portMatch) {
|
|
428
|
+
return parseInt(portMatch[1], 10);
|
|
429
|
+
}
|
|
374
430
|
}
|
|
431
|
+
catch { }
|
|
375
432
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
433
|
+
}
|
|
434
|
+
// Try next.config.js/mjs (less common to have port there, but check anyway)
|
|
435
|
+
// Next.js port is usually in package.json scripts or CLI args
|
|
436
|
+
// Try nuxt.config.ts/js
|
|
437
|
+
for (const configFile of ['nuxt.config.ts', 'nuxt.config.js']) {
|
|
438
|
+
const configPath = pathModule.join(appPath, configFile);
|
|
439
|
+
if (fs.existsSync(configPath)) {
|
|
440
|
+
try {
|
|
441
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
442
|
+
const portMatch = content.match(/devServer\s*:\s*\{[^}]*port\s*:\s*(\d+)/s) ||
|
|
443
|
+
content.match(/port\s*:\s*(\d+)/);
|
|
444
|
+
if (portMatch) {
|
|
445
|
+
return parseInt(portMatch[1], 10);
|
|
446
|
+
}
|
|
381
447
|
}
|
|
448
|
+
catch { }
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return undefined;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Get default port for a framework (fallback if config file doesn't specify)
|
|
455
|
+
*/
|
|
456
|
+
getDefaultPortForFramework(framework) {
|
|
457
|
+
const portMap = {
|
|
458
|
+
nextjs: 3000,
|
|
459
|
+
nuxt: 3000,
|
|
460
|
+
vite: 5173,
|
|
461
|
+
react: 3000,
|
|
462
|
+
vue: 5173,
|
|
463
|
+
angular: 4200,
|
|
464
|
+
nestjs: 3000,
|
|
465
|
+
express: 3000,
|
|
466
|
+
};
|
|
467
|
+
return portMap[framework];
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Ensure all apps have unique ports.
|
|
471
|
+
* When multiple apps have the same port, increment subsequent ones.
|
|
472
|
+
*/
|
|
473
|
+
ensureUniquePorts(apps) {
|
|
474
|
+
const usedPorts = new Set();
|
|
475
|
+
for (const app of apps) {
|
|
476
|
+
// Skip libraries and apps without ports
|
|
477
|
+
if (app.type === 'library' || !app.port)
|
|
478
|
+
continue;
|
|
479
|
+
let port = app.port;
|
|
480
|
+
// If port is already used, find the next available one
|
|
481
|
+
while (usedPorts.has(port)) {
|
|
482
|
+
port++;
|
|
483
|
+
}
|
|
484
|
+
// Update app port if it changed
|
|
485
|
+
if (port !== app.port) {
|
|
486
|
+
app.port = port;
|
|
382
487
|
}
|
|
488
|
+
usedPorts.add(port);
|
|
383
489
|
}
|
|
384
490
|
}
|
|
385
491
|
async detectGit(root) {
|