genbox 1.0.74 → 1.0.76

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.
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extendCommand = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const api_1 = require("../api");
11
+ const genbox_selector_1 = require("../genbox-selector");
12
+ exports.extendCommand = new commander_1.Command('extend')
13
+ .description('Extend genbox and reset inactivity timer')
14
+ .argument('[name]', 'Name of the Genbox (optional - will auto-select or prompt)')
15
+ .argument('[hours]', 'Hours to extend (default: 1)', '1')
16
+ .option('--no-auto-destroy', 'Disable auto-destroy on inactivity')
17
+ .option('--enable-auto-destroy', 'Re-enable auto-destroy on inactivity')
18
+ .action(async (name, hoursArg, options) => {
19
+ try {
20
+ const hours = parseInt(hoursArg, 10) || 1;
21
+ // Select genbox
22
+ const { genbox: target, cancelled } = await (0, genbox_selector_1.selectGenbox)(name, {
23
+ selectMessage: 'Select a genbox to extend:',
24
+ });
25
+ if (cancelled) {
26
+ console.log(chalk_1.default.dim('Cancelled.'));
27
+ return;
28
+ }
29
+ if (!target) {
30
+ return;
31
+ }
32
+ if (target.status !== 'running') {
33
+ console.error(chalk_1.default.red(`Error: Genbox '${target.name}' is not running (status: ${target.status})`));
34
+ return;
35
+ }
36
+ // Determine disableAutoDestroy value
37
+ let disableAutoDestroy;
38
+ if (options.autoDestroy === false) {
39
+ disableAutoDestroy = true; // --no-auto-destroy flag
40
+ }
41
+ else if (options.enableAutoDestroy) {
42
+ disableAutoDestroy = false; // --enable-auto-destroy flag
43
+ }
44
+ const spinner = (0, ora_1.default)(`Extending ${target.name}...`).start();
45
+ const result = await (0, api_1.fetchApi)(`/genboxes/${target._id}/extend`, {
46
+ method: 'POST',
47
+ body: JSON.stringify({
48
+ hours,
49
+ disableAutoDestroy,
50
+ }),
51
+ });
52
+ spinner.stop();
53
+ if (result.success) {
54
+ console.log(chalk_1.default.green(`✓ ${result.message}`));
55
+ if (result.currentHourEnd) {
56
+ const endTime = new Date(result.currentHourEnd);
57
+ const minutesUntil = Math.ceil((endTime.getTime() - Date.now()) / (60 * 1000));
58
+ console.log(chalk_1.default.dim(` Current hour ends in: ${minutesUntil} minutes`));
59
+ }
60
+ console.log(chalk_1.default.dim(` Auto-destroy: ${result.autoDestroyEnabled ? 'enabled' : 'disabled'}`));
61
+ }
62
+ else {
63
+ console.error(chalk_1.default.red(`Error: ${result.message}`));
64
+ }
65
+ }
66
+ catch (error) {
67
+ if (error.name === 'ExitPromptError' || error.message?.includes('force closed')) {
68
+ console.log('');
69
+ console.log(chalk_1.default.dim('Cancelled.'));
70
+ return;
71
+ }
72
+ if (error instanceof api_1.AuthenticationError) {
73
+ (0, api_1.handleApiError)(error);
74
+ return;
75
+ }
76
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
77
+ }
78
+ });
@@ -337,12 +337,17 @@ async function runSoftRebuild(options) {
337
337
  log(`Warning: Database restore failed: ${error.message}`, 'error');
338
338
  }
339
339
  }
340
- // Step 8: Start PM2 services
340
+ // Step 8: Start PM2 services (only for apps with runner: pm2 or unspecified)
341
341
  onStep?.('Starting application services...');
342
342
  for (const app of resolved.apps) {
343
343
  const appConfig = config.apps[app.name];
344
344
  if (!appConfig)
345
345
  continue;
346
+ // Skip apps with runner: docker - they're already running via Docker Compose
347
+ if (appConfig.runner === 'docker') {
348
+ log(`Skipping ${app.name} (runner: docker, already started via Docker Compose)`, 'dim');
349
+ continue;
350
+ }
346
351
  // Find the repo path for this app
347
352
  const appPath = appConfig.path || app.name;
348
353
  const repoPath = resolved.repos.find(r => r.name === app.name)?.path ||
@@ -362,11 +367,12 @@ async function runSoftRebuild(options) {
362
367
  }
363
368
  }
364
369
  else {
365
- // Check for start script in package.json
366
- const hasStartScript = await sshExec(ip, keyPath, `grep -q '"start"' ${repoPath}/package.json 2>/dev/null && echo yes || echo no`, 10);
367
- if (hasStartScript.output === 'yes') {
368
- log(`Starting ${app.name} with PM2 (npm start)...`, 'info');
369
- const pm2Result = await sshExecStream(ip, keyPath, `cd ${repoPath} && source ~/.nvm/nvm.sh && pm2 start npm --name ${app.name} -- start`, {
370
+ // Use configured dev command, or fall back to dev script, then start script
371
+ const devCommand = appConfig.commands?.dev;
372
+ if (devCommand) {
373
+ // Use the configured dev command
374
+ log(`Starting ${app.name} with PM2 (${devCommand})...`, 'info');
375
+ const pm2Result = await sshExecStream(ip, keyPath, `cd ${repoPath} && source ~/.nvm/nvm.sh && pm2 start "pnpm run ${devCommand}" --name ${app.name}`, {
370
376
  onStdout: (line) => log(line, 'dim'),
371
377
  timeoutSecs: 60,
372
378
  });
@@ -374,6 +380,34 @@ async function runSoftRebuild(options) {
374
380
  log(`✓ Started ${app.name}`, 'success');
375
381
  }
376
382
  }
383
+ else {
384
+ // Check for dev script in package.json first, then start
385
+ const hasDevScript = await sshExec(ip, keyPath, `grep -q '"dev"' ${repoPath}/package.json 2>/dev/null && echo yes || echo no`, 10);
386
+ if (hasDevScript.output === 'yes') {
387
+ log(`Starting ${app.name} with PM2 (pnpm dev)...`, 'info');
388
+ const pm2Result = await sshExecStream(ip, keyPath, `cd ${repoPath} && source ~/.nvm/nvm.sh && pm2 start "pnpm run dev" --name ${app.name}`, {
389
+ onStdout: (line) => log(line, 'dim'),
390
+ timeoutSecs: 60,
391
+ });
392
+ if (pm2Result.success) {
393
+ log(`✓ Started ${app.name}`, 'success');
394
+ }
395
+ }
396
+ else {
397
+ // Fall back to start script
398
+ const hasStartScript = await sshExec(ip, keyPath, `grep -q '"start"' ${repoPath}/package.json 2>/dev/null && echo yes || echo no`, 10);
399
+ if (hasStartScript.output === 'yes') {
400
+ log(`Starting ${app.name} with PM2 (pnpm start)...`, 'info');
401
+ const pm2Result = await sshExecStream(ip, keyPath, `cd ${repoPath} && source ~/.nvm/nvm.sh && pm2 start "pnpm run start" --name ${app.name}`, {
402
+ onStdout: (line) => log(line, 'dim'),
403
+ timeoutSecs: 60,
404
+ });
405
+ if (pm2Result.success) {
406
+ log(`✓ Started ${app.name}`, 'success');
407
+ }
408
+ }
409
+ }
410
+ }
377
411
  }
378
412
  }
379
413
  // Step 9: Save PM2 process list
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ const validate_1 = require("./commands/validate");
30
30
  const migrate_1 = require("./commands/migrate");
31
31
  const ssh_setup_1 = require("./commands/ssh-setup");
32
32
  const rebuild_1 = require("./commands/rebuild");
33
+ const extend_1 = require("./commands/extend");
33
34
  program
34
35
  .addCommand(init_1.initCommand)
35
36
  .addCommand(create_1.createCommand)
@@ -52,5 +53,6 @@ program
52
53
  .addCommand(migrate_1.migrateCommand)
53
54
  .addCommand(migrate_1.deprecationsCommand)
54
55
  .addCommand(ssh_setup_1.sshSetupCommand)
55
- .addCommand(rebuild_1.rebuildCommand);
56
+ .addCommand(rebuild_1.rebuildCommand)
57
+ .addCommand(extend_1.extendCommand);
56
58
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.74",
3
+ "version": "1.0.76",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {