genbox 1.0.2 → 1.0.4

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,364 @@
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
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.dbSyncCommand = void 0;
40
+ const commander_1 = require("commander");
41
+ const prompts = __importStar(require("@inquirer/prompts"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const ora_1 = __importDefault(require("ora"));
44
+ const config_loader_1 = require("../config-loader");
45
+ const api_1 = require("../api");
46
+ const genbox_selector_1 = require("../genbox-selector");
47
+ async function executeDbOperation(payload) {
48
+ return (0, api_1.fetchApi)('/genboxes/db', {
49
+ method: 'POST',
50
+ body: JSON.stringify(payload),
51
+ });
52
+ }
53
+ exports.dbSyncCommand = new commander_1.Command('db')
54
+ .description('Database operations for genbox environments');
55
+ // Subcommand: db sync
56
+ exports.dbSyncCommand
57
+ .command('sync [genbox]')
58
+ .description('Sync database from staging/production to a genbox')
59
+ .option('-s, --source <source>', 'Source environment: staging, production', 'staging')
60
+ .option('--collections <collections>', 'Comma-separated list of collections to sync')
61
+ .option('--exclude <collections>', 'Comma-separated list of collections to exclude')
62
+ .option('-f, --force', 'Skip confirmation prompt')
63
+ .option('--dry-run', 'Show what would be synced without actually syncing')
64
+ .action(async (genboxName, options) => {
65
+ try {
66
+ const configLoader = new config_loader_1.ConfigLoader();
67
+ const loadResult = await configLoader.load();
68
+ // Get genbox
69
+ // Select genbox
70
+ const result = await (0, genbox_selector_1.selectGenbox)(genboxName);
71
+ if (!result.genbox) {
72
+ if (!result.cancelled) {
73
+ console.log(chalk_1.default.yellow('No genbox selected'));
74
+ }
75
+ return;
76
+ }
77
+ const genbox = result.genbox.name;
78
+ const config = loadResult.config;
79
+ const source = options.source;
80
+ // Validate source environment exists
81
+ if (config.version === '3.0' && !config.environments?.[source]) {
82
+ console.log(chalk_1.default.yellow(`Environment '${source}' not configured in genbox.yaml`));
83
+ console.log(chalk_1.default.dim('Available environments:'));
84
+ for (const env of Object.keys(config.environments || {})) {
85
+ console.log(chalk_1.default.dim(` - ${env}`));
86
+ }
87
+ return;
88
+ }
89
+ // Get source URL
90
+ const envVars = configLoader.loadEnvVars(process.cwd());
91
+ const sourceUrlVar = source === 'production' ? 'PROD_MONGODB_URL' : 'STAGING_MONGODB_URL';
92
+ const sourceUrl = envVars[sourceUrlVar];
93
+ if (!sourceUrl) {
94
+ console.log(chalk_1.default.red(`${sourceUrlVar} not found in .env.genbox`));
95
+ console.log(chalk_1.default.dim(`Add ${sourceUrlVar}=mongodb+srv://... to your .env.genbox file`));
96
+ return;
97
+ }
98
+ // Display sync info
99
+ console.log('');
100
+ console.log(chalk_1.default.bold('Database Sync:'));
101
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
102
+ console.log(` ${chalk_1.default.bold('Genbox:')} ${genbox}`);
103
+ console.log(` ${chalk_1.default.bold('Source:')} ${source}`);
104
+ console.log(` ${chalk_1.default.bold('Database:')} ${config.project?.name || 'default'}`);
105
+ if (options.collections) {
106
+ console.log(` ${chalk_1.default.bold('Collections:')} ${options.collections}`);
107
+ }
108
+ if (options.exclude) {
109
+ console.log(` ${chalk_1.default.bold('Exclude:')} ${options.exclude}`);
110
+ }
111
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
112
+ // Warning for production
113
+ if (source === 'production') {
114
+ console.log('');
115
+ console.log(chalk_1.default.yellow('⚠ WARNING: Syncing from production database'));
116
+ }
117
+ // Dry run mode
118
+ if (options.dryRun) {
119
+ console.log('');
120
+ console.log(chalk_1.default.yellow('Dry run mode - no changes made'));
121
+ console.log(chalk_1.default.dim('Remove --dry-run to perform the sync'));
122
+ return;
123
+ }
124
+ // Confirmation
125
+ if (!options.force) {
126
+ console.log('');
127
+ console.log(chalk_1.default.yellow('⚠ This will replace all data in the genbox database!'));
128
+ const confirm = await prompts.confirm({
129
+ message: `Sync database from ${source} to ${genbox}?`,
130
+ default: false,
131
+ });
132
+ if (!confirm) {
133
+ console.log(chalk_1.default.dim('Cancelled.'));
134
+ return;
135
+ }
136
+ }
137
+ // Execute sync
138
+ const spinner = (0, ora_1.default)(`Syncing database from ${source}...`).start();
139
+ try {
140
+ const result = await executeDbOperation({
141
+ genboxName: genbox,
142
+ operation: 'copy',
143
+ source,
144
+ sourceUrl,
145
+ database: config.project?.name,
146
+ collections: options.collections?.split(',').map((c) => c.trim()),
147
+ excludeCollections: options.exclude?.split(',').map((c) => c.trim()),
148
+ });
149
+ spinner.succeed(chalk_1.default.green('Database synced successfully!'));
150
+ if (result.stats) {
151
+ console.log('');
152
+ console.log(chalk_1.default.bold('Sync Statistics:'));
153
+ console.log(` Collections: ${result.stats.collections || 0}`);
154
+ console.log(` Documents: ${result.stats.documents || 0}`);
155
+ console.log(` Size: ${result.stats.size || 'N/A'}`);
156
+ console.log(` Duration: ${result.stats.duration || 'N/A'}`);
157
+ }
158
+ }
159
+ catch (error) {
160
+ spinner.fail(chalk_1.default.red('Sync failed'));
161
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
162
+ if (error instanceof api_1.AuthenticationError) {
163
+ console.log(chalk_1.default.yellow('\nRun: genbox login'));
164
+ }
165
+ }
166
+ }
167
+ catch (error) {
168
+ if (error.name === 'ExitPromptError') {
169
+ console.log(chalk_1.default.dim('\nCancelled.'));
170
+ return;
171
+ }
172
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
173
+ }
174
+ });
175
+ // Subcommand: db status
176
+ exports.dbSyncCommand
177
+ .command('status [genbox]')
178
+ .description('Show database status for a genbox')
179
+ .action(async (genboxName) => {
180
+ try {
181
+ const configLoader = new config_loader_1.ConfigLoader();
182
+ const loadResult = await configLoader.load();
183
+ // Select genbox
184
+ const selectResult = await (0, genbox_selector_1.selectGenbox)(genboxName);
185
+ if (!selectResult.genbox) {
186
+ if (!selectResult.cancelled) {
187
+ console.log(chalk_1.default.yellow('No genbox selected'));
188
+ }
189
+ return;
190
+ }
191
+ const genbox = selectResult.genbox.name;
192
+ const spinner = (0, ora_1.default)('Fetching database status...').start();
193
+ try {
194
+ const result = await executeDbOperation({
195
+ genboxName: genbox,
196
+ operation: 'status',
197
+ });
198
+ spinner.stop();
199
+ console.log('');
200
+ console.log(chalk_1.default.bold(`Database Status: ${genbox}`));
201
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
202
+ if (result.status === 'connected') {
203
+ console.log(` ${chalk_1.default.bold('Status:')} ${chalk_1.default.green('Connected')}`);
204
+ }
205
+ else {
206
+ console.log(` ${chalk_1.default.bold('Status:')} ${chalk_1.default.red('Disconnected')}`);
207
+ }
208
+ if (result.mode) {
209
+ console.log(` ${chalk_1.default.bold('Mode:')} ${result.mode}`);
210
+ }
211
+ if (result.source) {
212
+ console.log(` ${chalk_1.default.bold('Source:')} ${result.source}`);
213
+ }
214
+ if (result.database) {
215
+ console.log(` ${chalk_1.default.bold('Database:')} ${result.database}`);
216
+ }
217
+ if (result.collections) {
218
+ console.log(` ${chalk_1.default.bold('Collections:')} ${result.collections}`);
219
+ }
220
+ if (result.size) {
221
+ console.log(` ${chalk_1.default.bold('Size:')} ${result.size}`);
222
+ }
223
+ if (result.lastSync) {
224
+ console.log(` ${chalk_1.default.bold('Last Sync:')} ${result.lastSync}`);
225
+ }
226
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
227
+ }
228
+ catch (error) {
229
+ spinner.fail(chalk_1.default.red('Failed to get status'));
230
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
231
+ }
232
+ }
233
+ catch (error) {
234
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
235
+ }
236
+ });
237
+ // Subcommand: db restore
238
+ exports.dbSyncCommand
239
+ .command('restore [genbox]')
240
+ .description('Restore database from a backup')
241
+ .option('-f, --file <file>', 'Path to backup file (local or S3 URL)')
242
+ .option('--force', 'Skip confirmation prompt')
243
+ .action(async (genboxName, options) => {
244
+ try {
245
+ const configLoader = new config_loader_1.ConfigLoader();
246
+ const loadResult = await configLoader.load();
247
+ // Select genbox
248
+ const selectResult = await (0, genbox_selector_1.selectGenbox)(genboxName);
249
+ if (!selectResult.genbox) {
250
+ if (!selectResult.cancelled) {
251
+ console.log(chalk_1.default.yellow('No genbox selected'));
252
+ }
253
+ return;
254
+ }
255
+ const genbox = selectResult.genbox.name;
256
+ if (!options.file) {
257
+ // List available backups
258
+ console.log(chalk_1.default.blue('Fetching available backups...'));
259
+ try {
260
+ const result = await (0, api_1.fetchApi)(`/genboxes/${genbox}/backups`);
261
+ if (!result.backups || result.backups.length === 0) {
262
+ console.log(chalk_1.default.yellow('No backups available'));
263
+ return;
264
+ }
265
+ console.log('');
266
+ console.log(chalk_1.default.bold('Available Backups:'));
267
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
268
+ for (const backup of result.backups.slice(0, 10)) {
269
+ console.log(` ${backup.name} ${chalk_1.default.dim(backup.date)} ${chalk_1.default.dim(backup.size)}`);
270
+ }
271
+ console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
272
+ console.log('');
273
+ console.log(chalk_1.default.dim('Use: genbox db restore <genbox> --file <backup-name>'));
274
+ return;
275
+ }
276
+ catch (error) {
277
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
278
+ return;
279
+ }
280
+ }
281
+ // Confirmation
282
+ if (!options.force) {
283
+ console.log('');
284
+ console.log(chalk_1.default.yellow('⚠ This will replace all data in the genbox database!'));
285
+ const confirm = await prompts.confirm({
286
+ message: `Restore database from ${options.file}?`,
287
+ default: false,
288
+ });
289
+ if (!confirm) {
290
+ console.log(chalk_1.default.dim('Cancelled.'));
291
+ return;
292
+ }
293
+ }
294
+ // Execute restore
295
+ const spinner = (0, ora_1.default)('Restoring database...').start();
296
+ try {
297
+ const result = await executeDbOperation({
298
+ genboxName: genbox,
299
+ operation: 'restore',
300
+ source: options.file,
301
+ });
302
+ spinner.succeed(chalk_1.default.green('Database restored successfully!'));
303
+ if (result.stats) {
304
+ console.log('');
305
+ console.log(chalk_1.default.bold('Restore Statistics:'));
306
+ console.log(` Collections: ${result.stats.collections || 0}`);
307
+ console.log(` Documents: ${result.stats.documents || 0}`);
308
+ console.log(` Duration: ${result.stats.duration || 'N/A'}`);
309
+ }
310
+ }
311
+ catch (error) {
312
+ spinner.fail(chalk_1.default.red('Restore failed'));
313
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
314
+ }
315
+ }
316
+ catch (error) {
317
+ if (error.name === 'ExitPromptError') {
318
+ console.log(chalk_1.default.dim('\nCancelled.'));
319
+ return;
320
+ }
321
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
322
+ }
323
+ });
324
+ // Subcommand: db dump
325
+ exports.dbSyncCommand
326
+ .command('dump [genbox]')
327
+ .description('Create a database dump/backup')
328
+ .option('-o, --output <path>', 'Output path for the dump')
329
+ .action(async (genboxName, options) => {
330
+ try {
331
+ const configLoader = new config_loader_1.ConfigLoader();
332
+ const loadResult = await configLoader.load();
333
+ // Select genbox
334
+ const selectResult = await (0, genbox_selector_1.selectGenbox)(genboxName);
335
+ if (!selectResult.genbox) {
336
+ if (!selectResult.cancelled) {
337
+ console.log(chalk_1.default.yellow('No genbox selected'));
338
+ }
339
+ return;
340
+ }
341
+ const genbox = selectResult.genbox.name;
342
+ const spinner = (0, ora_1.default)('Creating database dump...').start();
343
+ try {
344
+ const result = await (0, api_1.fetchApi)(`/genboxes/${genbox}/db/dump`, {
345
+ method: 'POST',
346
+ body: JSON.stringify({ output: options.output }),
347
+ });
348
+ spinner.succeed(chalk_1.default.green('Database dump created!'));
349
+ if (result.path) {
350
+ console.log(` Location: ${result.path}`);
351
+ }
352
+ if (result.size) {
353
+ console.log(` Size: ${result.size}`);
354
+ }
355
+ }
356
+ catch (error) {
357
+ spinner.fail(chalk_1.default.red('Dump failed'));
358
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
359
+ }
360
+ }
361
+ catch (error) {
362
+ console.error(chalk_1.default.red(`Error: ${error.message}`));
363
+ }
364
+ });
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.destroyCommand = void 0;
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
- const inquirer_1 = __importDefault(require("inquirer"));
9
+ const confirm_1 = __importDefault(require("@inquirer/confirm"));
10
10
  const ora_1 = __importDefault(require("ora"));
11
11
  const api_1 = require("../api");
12
12
  const genbox_selector_1 = require("../genbox-selector");
@@ -33,15 +33,10 @@ exports.destroyCommand = new commander_1.Command('destroy')
33
33
  // 2. Confirm
34
34
  let confirmed = options.yes;
35
35
  if (!confirmed) {
36
- const answer = await inquirer_1.default.prompt([
37
- {
38
- type: 'confirm',
39
- name: 'confirmed',
40
- message: `Are you sure you want to PERMANENTLY destroy '${target.name}' (${target.ipAddress || 'no IP'})?`,
41
- default: false,
42
- },
43
- ]);
44
- confirmed = answer.confirmed;
36
+ confirmed = await (0, confirm_1.default)({
37
+ message: `Are you sure you want to PERMANENTLY destroy '${target.name}' (${target.ipAddress || 'no IP'})?`,
38
+ default: false,
39
+ });
45
40
  }
46
41
  if (!confirmed) {
47
42
  console.log('Operation cancelled.');