genbox 1.0.20 → 1.0.22

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.
@@ -110,8 +110,8 @@ exports.createCommand = new commander_1.Command('create')
110
110
  .option('--db-source <source>', 'Database source: staging, production')
111
111
  .option('-s, --size <size>', 'Server size: small, medium, large, xl')
112
112
  .option('-b, --branch <branch>', 'Git branch to checkout')
113
- .option('-nb, --new-branch <name>', 'Create a new branch with this name')
114
- .option('-sb, --source-branch <branch>', 'Source branch to create new branch from (defaults to current/default branch)')
113
+ .option('-n, --new-branch <name>', 'Create a new branch with this name')
114
+ .option('-f, --from-branch <branch>', 'Source branch to create new branch from (defaults to current/default branch)')
115
115
  .option('-y, --yes', 'Skip interactive prompts')
116
116
  .option('--dry-run', 'Show what would be created without actually creating')
117
117
  .action(async (name, options) => {
@@ -128,6 +128,20 @@ exports.createCommand = new commander_1.Command('create')
128
128
  // Support both v3 and v4 configs
129
129
  const config = loadResult.config;
130
130
  const profileResolver = new profile_resolver_1.ProfileResolver(configLoader);
131
+ // Validate branch options
132
+ if (options.newBranch && !options.fromBranch) {
133
+ console.error(chalk_1.default.red('Error: --new-branch (-n) requires --from-branch (-f) to specify the source branch'));
134
+ console.log(chalk_1.default.dim(' Example: genbox create my-env -n feature/new -f main'));
135
+ return;
136
+ }
137
+ // Auto-generate branch name if only -f is provided
138
+ let newBranchName = options.newBranch;
139
+ if (options.fromBranch && !options.newBranch) {
140
+ // Generate unique branch name: {genbox-name}-{short-timestamp}
141
+ const timestamp = Date.now().toString(36); // Short alphanumeric timestamp
142
+ newBranchName = `${name}-${timestamp}`;
143
+ console.log(chalk_1.default.dim(` Auto-generated branch name: ${newBranchName}`));
144
+ }
131
145
  // Build create options
132
146
  const createOptions = {
133
147
  name,
@@ -139,8 +153,8 @@ exports.createCommand = new commander_1.Command('create')
139
153
  dbSource: options.dbSource,
140
154
  size: options.size,
141
155
  branch: options.branch,
142
- newBranch: options.newBranch,
143
- sourceBranch: options.sourceBranch,
156
+ newBranch: newBranchName,
157
+ sourceBranch: options.fromBranch,
144
158
  yes: options.yes,
145
159
  dryRun: options.dryRun,
146
160
  };
@@ -627,6 +641,11 @@ function buildPayload(resolved, config, publicKey, privateKey, configLoader) {
627
641
  mode: i.mode,
628
642
  })),
629
643
  database: resolved.database,
644
+ // Configuration tracking (for rebuild)
645
+ profile: resolved.profile,
646
+ branch: resolved.repos[0]?.branch,
647
+ newBranch: resolved.repos[0]?.newBranch,
648
+ sourceBranch: resolved.repos[0]?.sourceBranch,
630
649
  };
631
650
  }
632
651
  /**
@@ -47,6 +47,7 @@ const os = __importStar(require("os"));
47
47
  const config_loader_1 = require("../config-loader");
48
48
  const profile_resolver_1 = require("../profile-resolver");
49
49
  const api_1 = require("../api");
50
+ const genbox_selector_1 = require("../genbox-selector");
50
51
  const schema_v4_1 = require("../schema-v4");
51
52
  function getPublicSshKey() {
52
53
  const home = os.homedir();
@@ -76,10 +77,6 @@ function getPrivateSshKey() {
76
77
  }
77
78
  return undefined;
78
79
  }
79
- async function findGenboxByName(name) {
80
- const genboxes = await (0, api_1.fetchApi)('/genboxes');
81
- return genboxes.find((g) => g.name === name);
82
- }
83
80
  async function rebuildGenbox(id, payload) {
84
81
  return (0, api_1.fetchApi)(`/genboxes/${id}/rebuild`, {
85
82
  method: 'POST',
@@ -421,34 +418,48 @@ async function promptForBranchOptions(resolved, config) {
421
418
  }
422
419
  exports.rebuildCommand = new commander_1.Command('rebuild')
423
420
  .description('Rebuild an existing Genbox environment with updated configuration')
424
- .argument('<name>', 'Name of the Genbox to rebuild')
421
+ .argument('[name]', 'Name of the Genbox to rebuild (optional - will prompt if not provided)')
425
422
  .option('-p, --profile <profile>', 'Use a predefined profile')
423
+ .option('-a, --all', 'Select from all genboxes (not just current project)')
426
424
  .option('-b, --branch <branch>', 'Git branch to checkout')
427
- .option('-nb, --new-branch <name>', 'Create a new branch with this name')
428
- .option('-sb, --source-branch <branch>', 'Source branch to create new branch from')
425
+ .option('-n, --new-branch <name>', 'Create a new branch with this name')
426
+ .option('-f, --from-branch <branch>', 'Source branch to create new branch from')
429
427
  .option('-y, --yes', 'Skip interactive prompts')
430
428
  .action(async (name, options) => {
431
429
  try {
432
- // Find existing genbox
433
- const spinner = (0, ora_1.default)(`Finding Genbox '${name}'...`).start();
434
- let genbox;
435
- try {
436
- genbox = await findGenboxByName(name);
437
- }
438
- catch (error) {
439
- spinner.fail(chalk_1.default.red(`Failed to find Genbox: ${error.message}`));
440
- if (error instanceof api_1.AuthenticationError) {
441
- console.log('');
442
- console.log(chalk_1.default.yellow(' Please authenticate first:'));
443
- console.log(chalk_1.default.cyan(' $ genbox login'));
444
- }
430
+ // Select genbox (interactive if no name provided)
431
+ const { genbox, cancelled } = await (0, genbox_selector_1.selectGenbox)(name, {
432
+ all: options.all,
433
+ selectMessage: 'Select a genbox to rebuild:',
434
+ });
435
+ if (cancelled) {
436
+ console.log(chalk_1.default.dim('Cancelled.'));
445
437
  return;
446
438
  }
447
439
  if (!genbox) {
448
- spinner.fail(chalk_1.default.red(`Genbox '${name}' not found`));
449
440
  return;
450
441
  }
451
- spinner.succeed(`Found Genbox '${name}'`);
442
+ const selectedName = genbox.name;
443
+ // Check if genbox has stored configuration (profile/apps/branch)
444
+ const storedProfile = genbox.profile;
445
+ const storedApps = genbox.apps && genbox.apps.length > 0 ? genbox.apps : null;
446
+ const storedBranch = genbox.branch;
447
+ const storedNewBranch = genbox.newBranch;
448
+ const storedSourceBranch = genbox.sourceBranch;
449
+ if (storedProfile || storedApps || storedBranch) {
450
+ console.log(chalk_1.default.dim(`Using stored configuration from '${selectedName}':`));
451
+ if (storedProfile)
452
+ console.log(chalk_1.default.dim(` Profile: ${storedProfile}`));
453
+ if (storedApps)
454
+ console.log(chalk_1.default.dim(` Apps: ${storedApps.join(', ')}`));
455
+ if (storedNewBranch) {
456
+ console.log(chalk_1.default.dim(` Branch: ${storedNewBranch} (created from ${storedSourceBranch || 'main'})`));
457
+ }
458
+ else if (storedBranch) {
459
+ console.log(chalk_1.default.dim(` Branch: ${storedBranch}`));
460
+ }
461
+ console.log('');
462
+ }
452
463
  // Load configuration
453
464
  const configLoader = new config_loader_1.ConfigLoader();
454
465
  const loadResult = await configLoader.load();
@@ -459,26 +470,50 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
459
470
  }
460
471
  const config = loadResult.config;
461
472
  const profileResolver = new profile_resolver_1.ProfileResolver(configLoader);
462
- // Build options for resolving
473
+ // Validate branch options
474
+ if (options.newBranch && !options.fromBranch) {
475
+ console.error(chalk_1.default.red('Error: --new-branch (-n) requires --from-branch (-f) to specify the source branch'));
476
+ console.log(chalk_1.default.dim(' Example: genbox rebuild my-env -n feature/new -f main'));
477
+ return;
478
+ }
479
+ // Auto-generate branch name if only -f is provided
480
+ let newBranchName = options.newBranch;
481
+ if (options.fromBranch && !options.newBranch) {
482
+ // Generate unique branch name: {genbox-name}-{short-timestamp}
483
+ const timestamp = Date.now().toString(36);
484
+ newBranchName = `${selectedName}-${timestamp}`;
485
+ console.log(chalk_1.default.dim(` Auto-generated branch name: ${newBranchName}`));
486
+ }
487
+ // Use stored profile/apps/branch if available and not overridden by CLI options
488
+ const effectiveProfile = options.profile || storedProfile;
489
+ const effectiveApps = storedApps; // Use stored apps for rebuild
490
+ // For branch: CLI options override, then stored newBranch (if it was created), then stored branch
491
+ const effectiveBranch = options.branch || storedNewBranch || storedBranch;
492
+ // For new branch creation: only use CLI options (user must explicitly request new branch on rebuild)
493
+ const effectiveNewBranch = newBranchName;
494
+ const effectiveSourceBranch = options.fromBranch;
495
+ // Build options for resolving - use stored config, skip interactive prompts
463
496
  const createOptions = {
464
- name,
465
- profile: options.profile,
466
- branch: options.branch,
467
- newBranch: options.newBranch,
468
- sourceBranch: options.sourceBranch,
469
- yes: options.yes,
497
+ name: selectedName,
498
+ profile: effectiveProfile,
499
+ apps: effectiveApps || undefined, // Pre-select stored apps
500
+ branch: effectiveBranch,
501
+ newBranch: effectiveNewBranch,
502
+ sourceBranch: effectiveSourceBranch,
503
+ // Skip interactive prompts if we have stored config
504
+ yes: options.yes || !!(storedProfile || storedApps),
470
505
  };
471
506
  console.log(chalk_1.default.blue('Resolving configuration...'));
472
507
  console.log('');
473
508
  let resolved = await profileResolver.resolve(config, createOptions);
474
- // Interactive branch selection if no branch was specified
475
- if (!options.branch && !options.newBranch && !options.yes && resolved.repos.length > 0) {
509
+ // Interactive branch selection only if no branch specified and no stored branch
510
+ if (!options.branch && !storedBranch && !options.newBranch && !options.yes && resolved.repos.length > 0) {
476
511
  resolved = await promptForBranchOptions(resolved, config);
477
512
  }
478
513
  // Display what will be rebuilt
479
514
  console.log(chalk_1.default.bold('Rebuild Configuration:'));
480
515
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
481
- console.log(` ${chalk_1.default.bold('Name:')} ${name}`);
516
+ console.log(` ${chalk_1.default.bold('Name:')} ${selectedName}`);
482
517
  console.log(` ${chalk_1.default.bold('Project:')} ${resolved.project.name}`);
483
518
  if (resolved.profile) {
484
519
  console.log(` ${chalk_1.default.bold('Profile:')} ${resolved.profile}`);
@@ -509,7 +544,7 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
509
544
  console.log(chalk_1.default.yellow('All unsaved work on the server will be lost.'));
510
545
  console.log('');
511
546
  const confirm = await prompts.confirm({
512
- message: `Rebuild genbox '${name}'?`,
547
+ message: `Rebuild genbox '${selectedName}'?`,
513
548
  default: false,
514
549
  });
515
550
  if (!confirm) {
@@ -539,15 +574,15 @@ exports.rebuildCommand = new commander_1.Command('rebuild')
539
574
  // Build payload
540
575
  const payload = buildRebuildPayload(resolved, config, publicKey, privateKeyContent, configLoader);
541
576
  // Execute rebuild
542
- const rebuildSpinner = (0, ora_1.default)(`Rebuilding Genbox '${name}'...`).start();
577
+ const rebuildSpinner = (0, ora_1.default)(`Rebuilding Genbox '${selectedName}'...`).start();
543
578
  try {
544
579
  await rebuildGenbox(genbox._id, payload);
545
- rebuildSpinner.succeed(chalk_1.default.green(`Genbox '${name}' rebuild initiated!`));
580
+ rebuildSpinner.succeed(chalk_1.default.green(`Genbox '${selectedName}' rebuild initiated!`));
546
581
  console.log('');
547
582
  console.log(chalk_1.default.dim('Server is rebuilding. This may take a few minutes.'));
548
583
  console.log(chalk_1.default.dim('SSH connection will be temporarily unavailable.'));
549
584
  console.log('');
550
- console.log(`Run ${chalk_1.default.cyan(`genbox status ${name}`)} to check progress.`);
585
+ console.log(`Run ${chalk_1.default.cyan(`genbox status ${selectedName}`)} to check progress.`);
551
586
  }
552
587
  catch (error) {
553
588
  rebuildSpinner.fail(chalk_1.default.red(`Failed to rebuild: ${error.message}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {