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.
- package/dist/commands/create.js +369 -130
- package/dist/commands/db-sync.js +364 -0
- package/dist/commands/destroy.js +5 -10
- package/dist/commands/init.js +669 -402
- package/dist/commands/profiles.js +333 -0
- package/dist/commands/push.js +140 -47
- package/dist/config-loader.js +529 -0
- package/dist/genbox-selector.js +5 -8
- package/dist/index.js +5 -1
- package/dist/profile-resolver.js +547 -0
- package/dist/scanner/compose-parser.js +441 -0
- package/dist/scanner/config-generator.js +620 -0
- package/dist/scanner/env-analyzer.js +503 -0
- package/dist/scanner/framework-detector.js +621 -0
- package/dist/scanner/index.js +424 -0
- package/dist/scanner/runtime-detector.js +330 -0
- package/dist/scanner/structure-detector.js +412 -0
- package/dist/scanner/types.js +7 -0
- package/dist/schema-v3.js +12 -0
- package/package.json +4 -1
|
@@ -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
|
+
});
|
package/dist/commands/destroy.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
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.');
|