genbox 1.0.17 → 1.0.18
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/commands/scan.js +56 -15
- package/package.json +1 -1
package/dist/commands/scan.js
CHANGED
|
@@ -136,7 +136,11 @@ exports.scanCommand = new commander_1.Command('scan')
|
|
|
136
136
|
.filter(([, app]) => app.type === 'frontend')
|
|
137
137
|
.map(([name]) => name);
|
|
138
138
|
if (frontendApps.length > 0) {
|
|
139
|
-
|
|
139
|
+
let serviceUrls = scanEnvFilesForUrls(detected.apps, cwd);
|
|
140
|
+
// In interactive mode, let user select which URLs to configure
|
|
141
|
+
if (isInteractive && serviceUrls.length > 0) {
|
|
142
|
+
serviceUrls = await interactiveUrlSelection(serviceUrls);
|
|
143
|
+
}
|
|
140
144
|
if (serviceUrls.length > 0) {
|
|
141
145
|
detected.service_urls = serviceUrls;
|
|
142
146
|
}
|
|
@@ -257,6 +261,36 @@ async function interactiveSelection(detected) {
|
|
|
257
261
|
}
|
|
258
262
|
return result;
|
|
259
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Interactive service URL selection
|
|
266
|
+
*/
|
|
267
|
+
async function interactiveUrlSelection(serviceUrls) {
|
|
268
|
+
if (serviceUrls.length === 0) {
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
console.log('');
|
|
272
|
+
console.log(chalk_1.default.blue('=== Detected Service URLs ==='));
|
|
273
|
+
console.log(chalk_1.default.dim('These are local/development URLs found in frontend env files.'));
|
|
274
|
+
console.log(chalk_1.default.dim('Select which ones need staging URL equivalents.\n'));
|
|
275
|
+
// Show detected URLs
|
|
276
|
+
for (const svc of serviceUrls) {
|
|
277
|
+
console.log(` ${chalk_1.default.cyan(svc.base_url)}`);
|
|
278
|
+
console.log(chalk_1.default.dim(` Used by: ${svc.used_by.slice(0, 3).join(', ')}${svc.used_by.length > 3 ? ` +${svc.used_by.length - 3} more` : ''}`));
|
|
279
|
+
}
|
|
280
|
+
console.log();
|
|
281
|
+
// Let user select which URLs to configure
|
|
282
|
+
const urlChoices = serviceUrls.map(svc => ({
|
|
283
|
+
name: `${svc.base_url} (${svc.used_by.length} var${svc.used_by.length > 1 ? 's' : ''})`,
|
|
284
|
+
value: svc.base_url,
|
|
285
|
+
checked: true, // Default: include all
|
|
286
|
+
}));
|
|
287
|
+
const selectedUrls = await prompts.checkbox({
|
|
288
|
+
message: 'Select service URLs to configure for staging:',
|
|
289
|
+
choices: urlChoices,
|
|
290
|
+
});
|
|
291
|
+
// Filter to selected URLs
|
|
292
|
+
return serviceUrls.filter(svc => selectedUrls.includes(svc.base_url));
|
|
293
|
+
}
|
|
260
294
|
/**
|
|
261
295
|
* Scan env files in app directories for service URLs
|
|
262
296
|
*/
|
|
@@ -270,25 +304,37 @@ function scanEnvFilesForUrls(apps, rootDir) {
|
|
|
270
304
|
const appDir = path.join(rootDir, app.path);
|
|
271
305
|
// Find env file
|
|
272
306
|
let envContent;
|
|
273
|
-
let envSource;
|
|
274
307
|
for (const pattern of envPatterns) {
|
|
275
308
|
const envPath = path.join(appDir, pattern);
|
|
276
309
|
if (fs.existsSync(envPath)) {
|
|
277
310
|
envContent = fs.readFileSync(envPath, 'utf8');
|
|
278
|
-
envSource = pattern;
|
|
279
311
|
break;
|
|
280
312
|
}
|
|
281
313
|
}
|
|
282
314
|
if (!envContent)
|
|
283
315
|
continue;
|
|
284
|
-
//
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
316
|
+
// Process each line individually
|
|
317
|
+
for (const line of envContent.split('\n')) {
|
|
318
|
+
// Skip comments and empty lines
|
|
319
|
+
const trimmedLine = line.trim();
|
|
320
|
+
if (!trimmedLine || trimmedLine.startsWith('#'))
|
|
321
|
+
continue;
|
|
322
|
+
// Parse VAR=value format
|
|
323
|
+
const lineMatch = trimmedLine.match(/^([A-Z_][A-Z0-9_]*)=["']?(.+?)["']?$/);
|
|
324
|
+
if (!lineMatch)
|
|
325
|
+
continue;
|
|
326
|
+
const varName = lineMatch[1];
|
|
327
|
+
const value = lineMatch[2];
|
|
328
|
+
// Skip URLs with @ symbol (credentials, connection strings)
|
|
329
|
+
if (value.includes('@'))
|
|
330
|
+
continue;
|
|
331
|
+
// Check if it's a URL
|
|
332
|
+
const urlMatch = value.match(/^(https?:\/\/[a-zA-Z0-9_.-]+(?::\d+)?)/);
|
|
333
|
+
if (!urlMatch)
|
|
334
|
+
continue;
|
|
335
|
+
const baseUrl = urlMatch[1];
|
|
290
336
|
// Extract hostname
|
|
291
|
-
const hostMatch =
|
|
337
|
+
const hostMatch = baseUrl.match(/^https?:\/\/([a-zA-Z0-9_.-]+)/);
|
|
292
338
|
if (!hostMatch)
|
|
293
339
|
continue;
|
|
294
340
|
const hostname = hostMatch[1];
|
|
@@ -298,11 +344,6 @@ function scanEnvFilesForUrls(apps, rootDir) {
|
|
|
298
344
|
/^\d+\.\d+\.\d+\.\d+$/.test(hostname);
|
|
299
345
|
if (!isLocalUrl)
|
|
300
346
|
continue;
|
|
301
|
-
// Extract base URL
|
|
302
|
-
const baseMatch = fullUrl.match(/^(https?:\/\/[a-zA-Z0-9_.-]+(?::\d+)?)/);
|
|
303
|
-
if (!baseMatch)
|
|
304
|
-
continue;
|
|
305
|
-
const baseUrl = baseMatch[1];
|
|
306
347
|
// Add to map
|
|
307
348
|
if (!serviceUrls.has(baseUrl)) {
|
|
308
349
|
serviceUrls.set(baseUrl, { vars: new Set(), apps: new Set() });
|