genbox 1.0.13 → 1.0.14

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.
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -7,21 +40,152 @@ exports.destroyCommand = void 0;
7
40
  const commander_1 = require("commander");
8
41
  const chalk_1 = __importDefault(require("chalk"));
9
42
  const confirm_1 = __importDefault(require("@inquirer/confirm"));
43
+ const select_1 = __importDefault(require("@inquirer/select"));
44
+ const prompts = __importStar(require("@inquirer/prompts"));
10
45
  const ora_1 = __importDefault(require("ora"));
11
46
  const api_1 = require("../api");
12
47
  const genbox_selector_1 = require("../genbox-selector");
13
48
  const ssh_config_1 = require("../ssh-config");
49
+ /**
50
+ * Format genbox for display in selection list
51
+ */
52
+ function formatGenboxChoice(g) {
53
+ const statusColor = g.status === 'running' ? chalk_1.default.green :
54
+ g.status === 'terminated' ? chalk_1.default.red : chalk_1.default.yellow;
55
+ const projectInfo = g.project ? chalk_1.default.dim(` [${g.project}]`) : '';
56
+ return {
57
+ name: `${g.name} ${statusColor(`(${g.status})`)} ${chalk_1.default.dim(g.ipAddress || 'No IP')}${projectInfo}`,
58
+ value: g,
59
+ };
60
+ }
61
+ /**
62
+ * Handle bulk delete flow when --all flag is used without a name
63
+ */
64
+ async function handleBulkDelete(options) {
65
+ const projectName = (0, genbox_selector_1.getProjectContext)();
66
+ // Fetch both project and global genboxes for counts
67
+ const allGenboxes = await (0, genbox_selector_1.getGenboxes)({ all: true });
68
+ const projectGenboxes = projectName
69
+ ? allGenboxes.filter(g => g.project === projectName || g.workspace === projectName)
70
+ : [];
71
+ if (allGenboxes.length === 0) {
72
+ console.log(chalk_1.default.yellow('No genboxes found.'));
73
+ return;
74
+ }
75
+ let targetGenboxes;
76
+ let scopeLabel;
77
+ // If in project context, ask user to choose scope
78
+ if (projectName && projectGenboxes.length > 0) {
79
+ const scopeChoices = [
80
+ {
81
+ name: `Delete from ${chalk_1.default.cyan(projectName)} project ${chalk_1.default.dim(`(${projectGenboxes.length} genbox${projectGenboxes.length === 1 ? '' : 'es'})`)}`,
82
+ value: 'project',
83
+ },
84
+ {
85
+ name: `Delete globally ${chalk_1.default.dim(`(${allGenboxes.length} genbox${allGenboxes.length === 1 ? '' : 'es'})`)}`,
86
+ value: 'global',
87
+ },
88
+ ];
89
+ const scope = await (0, select_1.default)({
90
+ message: 'Select deletion scope:',
91
+ choices: scopeChoices,
92
+ });
93
+ if (scope === 'project') {
94
+ targetGenboxes = projectGenboxes;
95
+ scopeLabel = `project '${projectName}'`;
96
+ }
97
+ else {
98
+ targetGenboxes = allGenboxes;
99
+ scopeLabel = 'all projects';
100
+ }
101
+ }
102
+ else {
103
+ // Not in project context or no project genboxes - show all
104
+ targetGenboxes = allGenboxes;
105
+ scopeLabel = 'all projects';
106
+ console.log(chalk_1.default.dim(`Found ${allGenboxes.length} genbox${allGenboxes.length === 1 ? '' : 'es'} globally.\n`));
107
+ }
108
+ if (targetGenboxes.length === 0) {
109
+ console.log(chalk_1.default.yellow(`No genboxes found in ${scopeLabel}.`));
110
+ return;
111
+ }
112
+ // Show checkbox selection for genboxes
113
+ const choices = targetGenboxes.map(g => ({
114
+ ...formatGenboxChoice(g),
115
+ checked: false, // Default to unchecked for safety
116
+ }));
117
+ console.log(''); // Add spacing
118
+ const selectedGenboxes = await prompts.checkbox({
119
+ message: `Select genboxes to destroy from ${scopeLabel}:`,
120
+ choices,
121
+ required: true,
122
+ });
123
+ if (selectedGenboxes.length === 0) {
124
+ console.log(chalk_1.default.yellow('No genboxes selected.'));
125
+ return;
126
+ }
127
+ // Show summary and confirm
128
+ console.log('');
129
+ console.log(chalk_1.default.yellow.bold('⚠️ The following genboxes will be PERMANENTLY destroyed:'));
130
+ console.log('');
131
+ selectedGenboxes.forEach(g => {
132
+ const statusColor = g.status === 'running' ? chalk_1.default.green : chalk_1.default.yellow;
133
+ console.log(` ${chalk_1.default.red('•')} ${g.name} ${statusColor(`(${g.status})`)} ${chalk_1.default.dim(g.ipAddress || 'No IP')}`);
134
+ });
135
+ console.log('');
136
+ let confirmed = options.yes;
137
+ if (!confirmed) {
138
+ confirmed = await (0, confirm_1.default)({
139
+ message: `Are you sure you want to destroy ${chalk_1.default.red(selectedGenboxes.length)} genbox${selectedGenboxes.length === 1 ? '' : 'es'}?`,
140
+ default: false,
141
+ });
142
+ }
143
+ if (!confirmed) {
144
+ console.log(chalk_1.default.dim('Operation cancelled.'));
145
+ return;
146
+ }
147
+ // Delete each genbox
148
+ console.log('');
149
+ let successCount = 0;
150
+ let failCount = 0;
151
+ for (const genbox of selectedGenboxes) {
152
+ const spinner = (0, ora_1.default)(`Destroying ${genbox.name}...`).start();
153
+ try {
154
+ await (0, api_1.fetchApi)(`/genboxes/${genbox._id}`, { method: 'DELETE' });
155
+ (0, ssh_config_1.removeSshConfigEntry)(genbox.name);
156
+ spinner.succeed(chalk_1.default.green(`Destroyed '${genbox.name}'`));
157
+ successCount++;
158
+ }
159
+ catch (error) {
160
+ spinner.fail(chalk_1.default.red(`Failed to destroy '${genbox.name}': ${error.message}`));
161
+ failCount++;
162
+ }
163
+ }
164
+ // Summary
165
+ console.log('');
166
+ if (failCount === 0) {
167
+ console.log(chalk_1.default.green.bold(`✓ Successfully destroyed ${successCount} genbox${successCount === 1 ? '' : 'es'}.`));
168
+ }
169
+ else {
170
+ console.log(chalk_1.default.yellow(`Completed: ${successCount} destroyed, ${failCount} failed.`));
171
+ }
172
+ }
14
173
  exports.destroyCommand = new commander_1.Command('destroy')
15
174
  .alias('delete')
16
- .description('Destroy a Genbox')
175
+ .description('Destroy one or more Genboxes')
17
176
  .argument('[name]', 'Name of the Genbox to destroy (optional - will prompt if not provided)')
18
177
  .option('-y, --yes', 'Skip confirmation')
19
- .option('-a, --all', 'Select from all genboxes (not just current project)')
178
+ .option('-a, --all', 'Bulk delete mode - select multiple genboxes to destroy')
20
179
  .action(async (name, options) => {
21
180
  try {
22
- // 1. Select Genbox (interactive if no name provided)
181
+ // Bulk delete mode when --all is used without a specific name
182
+ if (options.all && !name) {
183
+ await handleBulkDelete(options);
184
+ return;
185
+ }
186
+ // Single genbox deletion flow
23
187
  const { genbox: target, cancelled } = await (0, genbox_selector_1.selectGenbox)(name, {
24
- all: options.all,
188
+ all: options.all, // If --all with name, search in all genboxes
25
189
  selectMessage: 'Select a genbox to destroy:',
26
190
  });
27
191
  if (cancelled) {
@@ -31,7 +195,7 @@ exports.destroyCommand = new commander_1.Command('destroy')
31
195
  if (!target) {
32
196
  return;
33
197
  }
34
- // 2. Confirm
198
+ // Confirm
35
199
  let confirmed = options.yes;
36
200
  if (!confirmed) {
37
201
  confirmed = await (0, confirm_1.default)({
@@ -43,7 +207,7 @@ exports.destroyCommand = new commander_1.Command('destroy')
43
207
  console.log('Operation cancelled.');
44
208
  return;
45
209
  }
46
- // 3. Delete
210
+ // Delete
47
211
  const spinner = (0, ora_1.default)(`Destroying ${target.name}...`).start();
48
212
  await (0, api_1.fetchApi)(`/genboxes/${target._id}`, {
49
213
  method: 'DELETE',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {