genbox 1.0.52 → 1.0.54

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.
@@ -236,7 +236,7 @@ exports.createCommand = new commander_1.Command('create')
236
236
  .option('-a, --apps <apps>', 'Comma-separated list of apps to include')
237
237
  .option('--add-apps <apps>', 'Add apps to the profile')
238
238
  .option('--api <mode>', 'API mode: local, staging, production')
239
- .option('--db <mode>', 'Database mode: none, local, copy, remote')
239
+ .option('--db <mode>', 'Database mode: none, fresh, copy, remote')
240
240
  .option('--db-source <source>', 'Database source: staging, production')
241
241
  .option('--db-dump <path>', 'Use existing mongodump file instead of creating one')
242
242
  .option('--db-copy-remote', 'Copy database on the server (requires publicly accessible DB)')
@@ -550,14 +550,27 @@ exports.createCommand = new commander_1.Command('create')
550
550
  snapshotId = snapshotResult.snapshotId;
551
551
  snapshotS3Key = snapshotResult.s3Key;
552
552
  // Cleanup local dump since it's now in S3
553
- (0, db_utils_1.cleanupDump)(localDumpPath);
553
+ if (localDumpPath)
554
+ (0, db_utils_1.cleanupDump)(localDumpPath);
554
555
  localDumpPath = undefined;
555
556
  }
556
557
  else {
557
- uploadSpinner.warn(chalk_1.default.yellow(`Snapshot upload failed: ${snapshotResult.error}`));
558
- console.log(chalk_1.default.dim(' Will fall back to direct SCP upload after genbox creation'));
558
+ uploadSpinner.fail(chalk_1.default.red('Database snapshot upload failed'));
559
+ console.log(chalk_1.default.dim(` Error: ${snapshotResult.error}`));
560
+ console.log(chalk_1.default.dim(' Try again later or use --db fresh to start with empty database.'));
561
+ if (localDumpPath)
562
+ (0, db_utils_1.cleanupDump)(localDumpPath);
563
+ return;
559
564
  }
560
565
  }
566
+ else {
567
+ // No project synced - can't upload to S3
568
+ console.log(chalk_1.default.red('Project not synced - cannot upload database snapshot.'));
569
+ console.log(chalk_1.default.dim(' Run `genbox init` first to sync your project, then try again.'));
570
+ if (localDumpPath)
571
+ (0, db_utils_1.cleanupDump)(localDumpPath);
572
+ return;
573
+ }
561
574
  }
562
575
  }
563
576
  // Build payload
@@ -572,14 +585,6 @@ exports.createCommand = new commander_1.Command('create')
572
585
  s3Key: snapshotS3Key,
573
586
  };
574
587
  }
575
- else if (localDumpPath) {
576
- // Fall back to SCP upload mode (no project or S3 upload failed)
577
- payloadResolved.database = {
578
- ...resolved.database,
579
- url: undefined,
580
- mode: 'copy-local',
581
- };
582
- }
583
588
  const payload = buildPayload(payloadResolved, config, publicKey, privateKeyContent, configLoader);
584
589
  // Create genbox
585
590
  const spinner = (0, ora_1.default)(`Creating Genbox '${name}'...`).start();
@@ -600,59 +605,6 @@ exports.createCommand = new commander_1.Command('create')
600
605
  }
601
606
  // Display results
602
607
  displayGenboxInfo(genbox, resolved);
603
- // Handle database upload if we have a local dump
604
- if (localDumpPath && genbox.ipAddress) {
605
- console.log('');
606
- console.log(chalk_1.default.blue('=== Database Restore ==='));
607
- // Wait for SSH access
608
- const sshSpinner = (0, ora_1.default)('Waiting for SSH access...').start();
609
- const sshReady = await (0, db_utils_1.waitForSshAccess)(genbox.ipAddress, 300, (msg) => {
610
- sshSpinner.text = msg;
611
- });
612
- if (!sshReady) {
613
- sshSpinner.fail(chalk_1.default.yellow('SSH not ready - database will need manual restore'));
614
- console.log(chalk_1.default.dim(' Run `genbox db sync` after the server is ready'));
615
- (0, db_utils_1.cleanupDump)(localDumpPath);
616
- }
617
- else {
618
- sshSpinner.succeed('SSH connected');
619
- // Upload dump
620
- const uploadSpinner = (0, ora_1.default)('Uploading database dump...').start();
621
- const uploadResult = await (0, db_utils_1.uploadDumpToGenbox)(localDumpPath, genbox.ipAddress, {
622
- onProgress: (msg) => uploadSpinner.text = msg,
623
- });
624
- if (!uploadResult.success) {
625
- uploadSpinner.fail(chalk_1.default.yellow('Upload failed - database will need manual restore'));
626
- console.log(chalk_1.default.dim(` ${uploadResult.error}`));
627
- console.log(chalk_1.default.dim(' Run `genbox db sync` after the server is ready'));
628
- (0, db_utils_1.cleanupDump)(localDumpPath);
629
- }
630
- else {
631
- uploadSpinner.succeed('Dump uploaded');
632
- // Trigger restore
633
- const restoreSpinner = (0, ora_1.default)('Restoring database...').start();
634
- const restoreResult = await (0, db_utils_1.runRemoteMongoRestore)(genbox.ipAddress, config.project.name, { onProgress: (msg) => restoreSpinner.text = msg });
635
- if (!restoreResult.success) {
636
- restoreSpinner.fail(chalk_1.default.yellow('Restore failed'));
637
- console.log(chalk_1.default.dim(` ${restoreResult.error}`));
638
- console.log(chalk_1.default.dim(' The dump file is on the server - you can restore manually'));
639
- }
640
- else {
641
- restoreSpinner.succeed(chalk_1.default.green('Database restored successfully!'));
642
- }
643
- // Cleanup local dump
644
- (0, db_utils_1.cleanupDump)(localDumpPath);
645
- }
646
- }
647
- }
648
- else if (localDumpPath) {
649
- // No IP yet - inform user to run db sync later
650
- console.log('');
651
- console.log(chalk_1.default.yellow('Database dump created but IP not yet assigned.'));
652
- console.log(chalk_1.default.dim(' Run `genbox db sync` once the server is ready to restore the database.'));
653
- // Keep the dump file - user might want to use it
654
- console.log(chalk_1.default.dim(` Dump file: ${localDumpPath}`));
655
- }
656
608
  // Inform user about server provisioning
657
609
  console.log('');
658
610
  console.log(chalk_1.default.dim('Server is provisioning. Run `genbox connect` once ready.'));
@@ -858,7 +858,8 @@ async function setupProfiles(detected, environments) {
858
858
  console.log(chalk_1.default.dim(` Connection: ${profile.default_connection}`));
859
859
  }
860
860
  if (profile.database) {
861
- console.log(chalk_1.default.dim(` Database: ${profile.database.mode}${profile.database.source ? ` from ${profile.database.source}` : ''}`));
861
+ const dbModeDisplay = profile.database.mode === 'local' ? 'fresh' : profile.database.mode;
862
+ console.log(chalk_1.default.dim(` Database: ${dbModeDisplay}${profile.database.source ? ` from ${profile.database.source}` : ''}`));
862
863
  }
863
864
  console.log('');
864
865
  }
@@ -321,18 +321,29 @@ class ProfileResolver {
321
321
  * Resolve database mode
322
322
  */
323
323
  async resolveDatabaseMode(config, options, profile) {
324
- // Helper to get MongoDB URL for an environment
324
+ // Load env vars from .env.genbox (where init stores MongoDB URLs)
325
+ const envVars = this.configLoader.loadEnvVars(process.cwd());
326
+ // Helper to get MongoDB URL from .env.genbox
327
+ // Matches what init saves: PROD_MONGODB_URL, STAGING_MONGODB_URL
325
328
  const getMongoUrl = (source) => {
326
- const envConfig = config.environments?.[source];
327
- return envConfig?.urls?.mongodb;
329
+ if (source === 'production') {
330
+ return envVars['PROD_MONGODB_URL'] || envVars['PRODUCTION_MONGODB_URL'];
331
+ }
332
+ else if (source === 'staging') {
333
+ return envVars['STAGING_MONGODB_URL'];
334
+ }
335
+ // Custom environments: {NAME}_MONGODB_URL
336
+ return envVars[`${source.toUpperCase()}_MONGODB_URL`];
328
337
  };
329
338
  // CLI flag takes precedence
330
339
  if (options.db) {
340
+ // Normalize 'fresh' to 'local' (fresh is the UI name, local is internal)
341
+ const dbMode = options.db === 'fresh' ? 'local' : options.db;
331
342
  const source = options.dbSource || profile.database?.source || 'staging';
332
343
  return {
333
- mode: options.db,
344
+ mode: dbMode,
334
345
  source,
335
- url: options.db === 'copy' ? getMongoUrl(source) : undefined,
346
+ url: dbMode === 'copy' ? getMongoUrl(source) : undefined,
336
347
  };
337
348
  }
338
349
  // Profile setting
@@ -374,6 +385,18 @@ class ProfileResolver {
374
385
  */
375
386
  async selectDatabaseModeInteractive(config) {
376
387
  console.log(chalk_1.default.cyan('\nšŸ—„ļø Database Configuration:\n'));
388
+ // Load env vars from .env.genbox (where init stores MongoDB URLs)
389
+ const envVars = this.configLoader.loadEnvVars(process.cwd());
390
+ // Helper to get MongoDB URL from .env.genbox
391
+ const getMongoUrl = (source) => {
392
+ if (source === 'production') {
393
+ return envVars['PROD_MONGODB_URL'] || envVars['PRODUCTION_MONGODB_URL'];
394
+ }
395
+ else if (source === 'staging') {
396
+ return envVars['STAGING_MONGODB_URL'];
397
+ }
398
+ return envVars[`${source.toUpperCase()}_MONGODB_URL`];
399
+ };
377
400
  const modeChoices = [
378
401
  { name: 'None (no database)', value: 'none' },
379
402
  { name: 'Fresh (empty database)', value: 'local' },
@@ -405,18 +428,14 @@ class ProfileResolver {
405
428
  }
406
429
  else if (answer.startsWith('copy-')) {
407
430
  const source = answer.replace('copy-', '');
408
- const envConfig = config.environments?.[source];
409
- const mongoUrl = envConfig?.urls?.mongodb;
410
- return { mode: 'copy', source, url: mongoUrl };
431
+ return { mode: 'copy', source, url: getMongoUrl(source) };
411
432
  }
412
433
  else if (answer.startsWith('remote-')) {
413
434
  const source = answer.replace('remote-', '');
414
- const envConfig = config.environments?.[source];
415
- const mongoUrl = envConfig?.urls?.mongodb;
416
435
  return {
417
436
  mode: 'remote',
418
437
  source,
419
- url: mongoUrl,
438
+ url: getMongoUrl(source),
420
439
  };
421
440
  }
422
441
  return { mode: 'local' };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.52",
3
+ "version": "1.0.54",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {