genbox 1.0.107 → 1.0.109

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.
@@ -1164,35 +1164,30 @@ async function setupProfiles(detected, environments) {
1164
1164
  }
1165
1165
  // Start with default profiles
1166
1166
  let profiles = { ...defaultProfiles };
1167
- // If there are existing profiles (including user-created ones), offer to retain them
1168
- if (Object.keys(existingProfiles).length > 0) {
1169
- console.log(chalk_1.default.dim('Found existing profiles in genbox.yaml:'));
1167
+ // If there are user-created profiles, offer to retain them
1168
+ if (Object.keys(userCreatedProfiles).length > 0) {
1169
+ console.log(chalk_1.default.dim('Found user-created profiles in genbox.yaml:'));
1170
1170
  console.log('');
1171
- // Display existing profiles with indication if they're user-created
1172
- for (const [name, profile] of Object.entries(existingProfiles)) {
1173
- const isUserCreated = !defaultProfileNames.has(name);
1174
- const label = isUserCreated ? chalk_1.default.yellow(' (user-created)') : chalk_1.default.dim(' (auto-generated)');
1175
- console.log(` ${chalk_1.default.cyan(name)}${label}`);
1171
+ // Display user-created profiles
1172
+ for (const [name, profile] of Object.entries(userCreatedProfiles)) {
1173
+ console.log(` ${chalk_1.default.cyan(name)}`);
1176
1174
  console.log(chalk_1.default.dim(` ${profile.description || 'No description'}`));
1177
1175
  console.log(chalk_1.default.dim(` Apps: ${profile.apps?.join(', ') || 'all'}`));
1178
1176
  console.log('');
1179
1177
  }
1180
- // Let user select which existing profiles to retain
1181
- const retainChoices = Object.entries(existingProfiles).map(([name, profile]) => {
1182
- const isUserCreated = !defaultProfileNames.has(name);
1183
- return {
1184
- name: `${name}${isUserCreated ? ' (user-created)' : ''} - ${profile.description || 'No description'}`,
1185
- value: name,
1186
- checked: isUserCreated, // User-created profiles are checked by default
1187
- };
1188
- });
1178
+ // Let user select which user-created profiles to retain
1179
+ const retainChoices = Object.entries(userCreatedProfiles).map(([name, profile]) => ({
1180
+ name: `${name} - ${profile.description || 'No description'}`,
1181
+ value: name,
1182
+ checked: true, // All user-created profiles are checked by default
1183
+ }));
1189
1184
  const retainedNames = await prompts.checkbox({
1190
- message: 'Select existing profiles to retain:',
1185
+ message: 'Select user-created profiles to retain:',
1191
1186
  choices: retainChoices,
1192
1187
  });
1193
- // Add retained profiles (they override defaults with same name)
1188
+ // Add retained user-created profiles
1194
1189
  for (const name of retainedNames) {
1195
- profiles[name] = existingProfiles[name];
1190
+ profiles[name] = userCreatedProfiles[name];
1196
1191
  }
1197
1192
  }
1198
1193
  if (Object.keys(profiles).length === 0) {
@@ -1204,8 +1199,8 @@ async function setupProfiles(detected, environments) {
1204
1199
  console.log(chalk_1.default.dim('Final profiles:'));
1205
1200
  console.log('');
1206
1201
  for (const [name, profile] of Object.entries(profiles)) {
1207
- const isRetained = existingProfiles[name] && !defaultProfileNames.has(name);
1208
- const label = isRetained ? chalk_1.default.yellow(' (retained)') : '';
1202
+ const isUserCreated = userCreatedProfiles[name] !== undefined;
1203
+ const label = isUserCreated ? chalk_1.default.yellow(' (user-created)') : '';
1209
1204
  console.log(` ${chalk_1.default.cyan(name)}${label}`);
1210
1205
  console.log(chalk_1.default.dim(` ${profile.description || 'No description'}`));
1211
1206
  console.log(chalk_1.default.dim(` Apps: ${profile.apps?.join(', ') || 'all'}`));
@@ -1560,12 +1555,23 @@ function generateEnvFile(projectName, detected, envVars, serviceUrlMappings) {
1560
1555
  content += `\n# Git authentication\n# GIT_TOKEN=ghp_xxxxxxxxxxxx\n`;
1561
1556
  }
1562
1557
  // Add app-specific sections from existing env files
1558
+ // Convert hardcoded localhost URLs to placeholders so they can be expanded based on profile
1563
1559
  const appEnvFiles = findAppEnvFiles(detected.apps, detected._meta.scanned_root);
1564
1560
  for (const envFile of appEnvFiles) {
1565
1561
  try {
1566
- const fileContent = fs_1.default.readFileSync(envFile.fullPath, 'utf8').trim();
1562
+ let fileContent = fs_1.default.readFileSync(envFile.fullPath, 'utf8').trim();
1567
1563
  if (fileContent) {
1564
+ // Replace hardcoded localhost URLs with placeholders
1565
+ // This allows the URLs to be expanded to local/staging/production based on profile
1566
+ for (const mapping of serviceUrlMappings) {
1567
+ // Escape special regex characters in the URL
1568
+ const escapedUrl = mapping.localUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1569
+ // Match the URL with optional quotes around it
1570
+ const urlPattern = new RegExp(`(["']?)${escapedUrl}\\1`, 'g');
1571
+ fileContent = fileContent.replace(urlPattern, `"\${${mapping.varName}}"`);
1572
+ }
1568
1573
  content += `\n# === ${envFile.appName} ===\n`;
1574
+ content += `# URLs use placeholders that get expanded based on profile (local vs staging)\n`;
1569
1575
  content += fileContent;
1570
1576
  content += '\n';
1571
1577
  }
@@ -438,8 +438,35 @@ exports.statusCommand = new commander_1.Command('status')
438
438
  console.log(chalk_1.default.dim(' Fix the error and run: cd ~/goodpass/api && docker compose up -d'));
439
439
  }
440
440
  else {
441
- // No errors in DB - services might just need to be started
442
- console.log(chalk_1.default.dim(' Try: cd ~/goodpass/api && docker compose up -d'));
441
+ // No errors in DB - try SSH fallback for older genboxes
442
+ // First check ~/.genbox-errors file (fast)
443
+ const savedErrors = sshExec(target.ipAddress, keyPath, 'cat ~/.genbox-errors 2>/dev/null || echo ""', 10);
444
+ if (savedErrors && savedErrors.trim()) {
445
+ console.log(chalk_1.default.red('[ERROR] Build failed during setup:'));
446
+ console.log(savedErrors);
447
+ console.log('');
448
+ console.log(chalk_1.default.dim(' Fix the error and run: cd ~/goodpass/api && docker compose up -d'));
449
+ }
450
+ else {
451
+ // No saved errors - check if there's a docker compose error
452
+ console.log(chalk_1.default.dim(' Checking for build errors...'));
453
+ const buildResult = sshExec(target.ipAddress, keyPath, 'cd ~/goodpass/api 2>/dev/null && docker compose build 2>&1 | tail -60 || echo ""', 120);
454
+ if (buildResult && (buildResult.includes('ERROR') || buildResult.includes('TS2') ||
455
+ buildResult.includes('failed') || buildResult.includes('ELIFECYCLE'))) {
456
+ console.log(chalk_1.default.red('[ERROR] Docker build failed:'));
457
+ const lines = buildResult.split('\n');
458
+ const errorLines = lines.filter(line => line.includes('ERROR') || line.includes('TS2') || line.includes('TS1') ||
459
+ line.includes('failed') || line.includes('exit code') ||
460
+ line.includes('>') || line.includes('^') ||
461
+ line.match(/^\s*\d+\s*\|/)).slice(-20);
462
+ console.log(errorLines.length > 0 ? errorLines.join('\n') : lines.slice(-25).join('\n'));
463
+ console.log('');
464
+ console.log(chalk_1.default.dim(' Fix the error and run: cd ~/goodpass/api && docker compose up -d'));
465
+ }
466
+ else {
467
+ console.log(chalk_1.default.dim(' Try: cd ~/goodpass/api && docker compose up -d'));
468
+ }
469
+ }
443
470
  }
444
471
  console.log('');
445
472
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.107",
3
+ "version": "1.0.109",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {