dockup-cli 1.0.0

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,584 @@
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.databaseList = databaseList;
40
+ exports.databaseCreate = databaseCreate;
41
+ exports.databaseRename = databaseRename;
42
+ exports.databaseDelete = databaseDelete;
43
+ exports.databaseCredentials = databaseCredentials;
44
+ exports.databaseInfo = databaseInfo;
45
+ exports.databaseLogs = databaseLogs;
46
+ exports.databaseRestart = databaseRestart;
47
+ exports.databaseSize = databaseSize;
48
+ exports.databaseBackupList = databaseBackupList;
49
+ exports.databaseBackupCreate = databaseBackupCreate;
50
+ const chalk_1 = __importDefault(require("chalk"));
51
+ const ora_1 = __importDefault(require("ora"));
52
+ const readline = __importStar(require("readline"));
53
+ const config_1 = require("../lib/config");
54
+ const api_1 = require("../lib/api");
55
+ const DB_TYPES = [
56
+ { name: 'PostgreSQL', value: 'postgresql' },
57
+ { name: 'MySQL', value: 'mysql' },
58
+ { name: 'MongoDB', value: 'mongodb' },
59
+ { name: 'Redis', value: 'redis' },
60
+ ];
61
+ function question(prompt) {
62
+ const rl = readline.createInterface({
63
+ input: process.stdin,
64
+ output: process.stdout
65
+ });
66
+ return new Promise((resolve) => {
67
+ rl.question(prompt, (answer) => {
68
+ rl.close();
69
+ resolve(answer);
70
+ });
71
+ });
72
+ }
73
+ function requireAuth() {
74
+ if (!(0, config_1.isLoggedIn)()) {
75
+ console.log(chalk_1.default.red('Not logged in. Run `dockup login` first.'));
76
+ return false;
77
+ }
78
+ return true;
79
+ }
80
+ function requireWorkspace() {
81
+ const ws = (0, config_1.getCurrentWorkspace)();
82
+ if (!ws) {
83
+ console.log(chalk_1.default.yellow('No workspace selected. Run `dockup workspace select` first.'));
84
+ return false;
85
+ }
86
+ return true;
87
+ }
88
+ function getStatusColor(status) {
89
+ switch (status?.toLowerCase()) {
90
+ case 'running':
91
+ case 'active':
92
+ return chalk_1.default.green(status);
93
+ case 'pending':
94
+ case 'creating':
95
+ return chalk_1.default.yellow(status);
96
+ case 'stopped':
97
+ case 'suspended':
98
+ return chalk_1.default.gray(status);
99
+ case 'error':
100
+ case 'failed':
101
+ return chalk_1.default.red(status);
102
+ default:
103
+ return chalk_1.default.dim(status || 'unknown');
104
+ }
105
+ }
106
+ async function databaseList() {
107
+ if (!requireAuth())
108
+ return;
109
+ if (!requireWorkspace())
110
+ return;
111
+ const workspace = (0, config_1.getCurrentWorkspace)();
112
+ const spinner = (0, ora_1.default)(`Fetching databases for "${workspace.name}"...`).start();
113
+ try {
114
+ const databases = await api_1.api.getDatabases(workspace.slug);
115
+ spinner.stop();
116
+ if (databases.length === 0) {
117
+ console.log(chalk_1.default.yellow(`\nNo databases in workspace "${workspace.name}". Create one with \`dockup db create\``));
118
+ return;
119
+ }
120
+ console.log(chalk_1.default.cyan(`\n Databases in "${workspace.name}":\n`));
121
+ databases.forEach((db) => {
122
+ const status = getStatusColor(db.status);
123
+ const type = chalk_1.default.dim(`[${db.dbType || db.type}]`);
124
+ console.log(` ${chalk_1.default.white(db.name)} ${type} - ${status}`);
125
+ });
126
+ console.log();
127
+ }
128
+ catch (error) {
129
+ spinner.fail(`Failed to fetch databases: ${error.message}`);
130
+ }
131
+ }
132
+ async function databaseCreate(options) {
133
+ if (!requireAuth())
134
+ return;
135
+ if (!requireWorkspace())
136
+ return;
137
+ const workspace = (0, config_1.getCurrentWorkspace)();
138
+ let { name, type } = options;
139
+ if (!name) {
140
+ name = await question('Database name: ');
141
+ if (!name || name.trim() === '') {
142
+ console.log(chalk_1.default.red('Name is required'));
143
+ return;
144
+ }
145
+ name = name.trim();
146
+ }
147
+ if (!type) {
148
+ console.log(chalk_1.default.cyan('\n Select database type:\n'));
149
+ DB_TYPES.forEach((t, i) => {
150
+ console.log(` ${i + 1}. ${t.name}`);
151
+ });
152
+ console.log();
153
+ const answer = await question('Enter number: ');
154
+ const index = parseInt(answer) - 1;
155
+ if (isNaN(index) || index < 0 || index >= DB_TYPES.length) {
156
+ console.log(chalk_1.default.red('Invalid selection'));
157
+ return;
158
+ }
159
+ type = DB_TYPES[index].value;
160
+ }
161
+ const spinner = (0, ora_1.default)(`Creating ${type} database "${name}"...`).start();
162
+ try {
163
+ const database = await api_1.api.createDatabase(workspace.slug, name, type);
164
+ spinner.succeed(`Database "${chalk_1.default.green(database.name)}" created successfully`);
165
+ console.log(chalk_1.default.dim(`\nDatabase is being provisioned. Run \`dockup db creds\` to get connection details.`));
166
+ }
167
+ catch (error) {
168
+ spinner.fail(`Failed to create database: ${error.message}`);
169
+ }
170
+ }
171
+ async function databaseRename(slug) {
172
+ if (!requireAuth())
173
+ return;
174
+ if (!requireWorkspace())
175
+ return;
176
+ const workspace = (0, config_1.getCurrentWorkspace)();
177
+ let dbSlug = slug;
178
+ // If no slug provided, let user select from list
179
+ if (!dbSlug) {
180
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
181
+ const databases = await api_1.api.getDatabases(workspace.slug);
182
+ spinner.stop();
183
+ if (databases.length === 0) {
184
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
185
+ return;
186
+ }
187
+ console.log(chalk_1.default.cyan('\n Select database to rename:\n'));
188
+ databases.forEach((db, i) => {
189
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
190
+ });
191
+ console.log();
192
+ const answer = await question('Enter number: ');
193
+ const index = parseInt(answer) - 1;
194
+ if (isNaN(index) || index < 0 || index >= databases.length) {
195
+ console.log(chalk_1.default.red('Invalid selection'));
196
+ return;
197
+ }
198
+ dbSlug = databases[index].slug;
199
+ }
200
+ const spinner = (0, ora_1.default)('Getting database info...').start();
201
+ const database = await api_1.api.getDatabase(workspace.slug, dbSlug);
202
+ spinner.stop();
203
+ const newName = await question(`New name for "${database.name}": `);
204
+ if (!newName || newName.trim() === '') {
205
+ console.log(chalk_1.default.dim('Cancelled'));
206
+ return;
207
+ }
208
+ const renameSpinner = (0, ora_1.default)('Renaming database...').start();
209
+ try {
210
+ const updated = await api_1.api.renameDatabase(workspace.slug, dbSlug, newName.trim());
211
+ renameSpinner.succeed(`Database renamed to "${chalk_1.default.green(updated.name)}"`);
212
+ }
213
+ catch (error) {
214
+ renameSpinner.fail(`Failed to rename database: ${error.message}`);
215
+ }
216
+ }
217
+ async function databaseDelete(slug) {
218
+ if (!requireAuth())
219
+ return;
220
+ if (!requireWorkspace())
221
+ return;
222
+ const workspace = (0, config_1.getCurrentWorkspace)();
223
+ let dbSlug = slug;
224
+ // If no slug provided, let user select from list
225
+ if (!dbSlug) {
226
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
227
+ const databases = await api_1.api.getDatabases(workspace.slug);
228
+ spinner.stop();
229
+ if (databases.length === 0) {
230
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
231
+ return;
232
+ }
233
+ console.log(chalk_1.default.cyan('\n Select database to delete:\n'));
234
+ databases.forEach((db, i) => {
235
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
236
+ });
237
+ console.log();
238
+ const answer = await question('Enter number: ');
239
+ const index = parseInt(answer) - 1;
240
+ if (isNaN(index) || index < 0 || index >= databases.length) {
241
+ console.log(chalk_1.default.red('Invalid selection'));
242
+ return;
243
+ }
244
+ dbSlug = databases[index].slug;
245
+ }
246
+ const spinner = (0, ora_1.default)('Getting database info...').start();
247
+ const database = await api_1.api.getDatabase(workspace.slug, dbSlug);
248
+ spinner.stop();
249
+ console.log(chalk_1.default.red(`\n WARNING: This will permanently delete "${database.name}"!\n`));
250
+ const answer = await question('Type "yes" to confirm: ');
251
+ if (answer.toLowerCase() !== 'yes') {
252
+ console.log(chalk_1.default.dim('Cancelled'));
253
+ return;
254
+ }
255
+ const deleteSpinner = (0, ora_1.default)('Deleting database...').start();
256
+ try {
257
+ await api_1.api.deleteDatabase(workspace.slug, dbSlug);
258
+ deleteSpinner.succeed(`Database "${database.name}" deleted`);
259
+ }
260
+ catch (error) {
261
+ deleteSpinner.fail(`Failed to delete database: ${error.message}`);
262
+ }
263
+ }
264
+ async function databaseCredentials(slug) {
265
+ if (!requireAuth())
266
+ return;
267
+ if (!requireWorkspace())
268
+ return;
269
+ const workspace = (0, config_1.getCurrentWorkspace)();
270
+ let dbSlug = slug;
271
+ // If no slug provided, let user select from list
272
+ if (!dbSlug) {
273
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
274
+ const databases = await api_1.api.getDatabases(workspace.slug);
275
+ spinner.stop();
276
+ if (databases.length === 0) {
277
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
278
+ return;
279
+ }
280
+ console.log(chalk_1.default.cyan('\n Select database:\n'));
281
+ databases.forEach((db, i) => {
282
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
283
+ });
284
+ console.log();
285
+ const answer = await question('Enter number: ');
286
+ const index = parseInt(answer) - 1;
287
+ if (isNaN(index) || index < 0 || index >= databases.length) {
288
+ console.log(chalk_1.default.red('Invalid selection'));
289
+ return;
290
+ }
291
+ dbSlug = databases[index].slug;
292
+ }
293
+ const spinner = (0, ora_1.default)('Fetching credentials...').start();
294
+ try {
295
+ const creds = await api_1.api.getDatabaseCredentials(workspace.slug, dbSlug);
296
+ spinner.stop();
297
+ console.log(chalk_1.default.cyan('\n Database Credentials:\n'));
298
+ console.log(` ${chalk_1.default.dim('Host:')} ${creds.host}`);
299
+ console.log(` ${chalk_1.default.dim('Port:')} ${creds.port}`);
300
+ console.log(` ${chalk_1.default.dim('Database:')} ${creds.database}`);
301
+ console.log(` ${chalk_1.default.dim('Username:')} ${creds.user || creds.username}`);
302
+ console.log(` ${chalk_1.default.dim('Password:')} ${creds.password}`);
303
+ if (creds.connectionString) {
304
+ console.log(chalk_1.default.cyan('\n Connection String:\n'));
305
+ console.log(` ${creds.connectionString}`);
306
+ }
307
+ console.log();
308
+ }
309
+ catch (error) {
310
+ spinner.fail(`Failed to fetch credentials: ${error.message}`);
311
+ }
312
+ }
313
+ async function databaseInfo(slug) {
314
+ if (!requireAuth())
315
+ return;
316
+ if (!requireWorkspace())
317
+ return;
318
+ const workspace = (0, config_1.getCurrentWorkspace)();
319
+ let dbSlug = slug;
320
+ // If no slug provided, let user select from list
321
+ if (!dbSlug) {
322
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
323
+ const databases = await api_1.api.getDatabases(workspace.slug);
324
+ spinner.stop();
325
+ if (databases.length === 0) {
326
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
327
+ return;
328
+ }
329
+ console.log(chalk_1.default.cyan('\n Select database:\n'));
330
+ databases.forEach((db, i) => {
331
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
332
+ });
333
+ console.log();
334
+ const answer = await question('Enter number: ');
335
+ const index = parseInt(answer) - 1;
336
+ if (isNaN(index) || index < 0 || index >= databases.length) {
337
+ console.log(chalk_1.default.red('Invalid selection'));
338
+ return;
339
+ }
340
+ dbSlug = databases[index].slug;
341
+ }
342
+ const spinner = (0, ora_1.default)('Fetching database info...').start();
343
+ try {
344
+ const db = await api_1.api.getDatabase(workspace.slug, dbSlug);
345
+ spinner.stop();
346
+ console.log(chalk_1.default.cyan('\n Database Info:\n'));
347
+ console.log(` ${chalk_1.default.dim('Name:')} ${db.name}`);
348
+ console.log(` ${chalk_1.default.dim('Type:')} ${db.dbType || db.type}`);
349
+ console.log(` ${chalk_1.default.dim('Version:')} ${db.dbVersion || db.version || 'latest'}`);
350
+ console.log(` ${chalk_1.default.dim('Status:')} ${getStatusColor(db.status)}`);
351
+ console.log(` ${chalk_1.default.dim('Slug:')} ${db.slug}`);
352
+ console.log(` ${chalk_1.default.dim('Created:')} ${new Date(db.createdAt).toLocaleString()}`);
353
+ console.log();
354
+ }
355
+ catch (error) {
356
+ spinner.fail(`Failed to fetch database info: ${error.message}`);
357
+ }
358
+ }
359
+ async function databaseLogs(slug, options) {
360
+ if (!requireAuth())
361
+ return;
362
+ if (!requireWorkspace())
363
+ return;
364
+ const workspace = (0, config_1.getCurrentWorkspace)();
365
+ let dbSlug = slug;
366
+ const tail = parseInt(options?.tail || '100');
367
+ // If no slug provided, let user select from list
368
+ if (!dbSlug) {
369
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
370
+ const databases = await api_1.api.getDatabases(workspace.slug);
371
+ spinner.stop();
372
+ if (databases.length === 0) {
373
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
374
+ return;
375
+ }
376
+ console.log(chalk_1.default.cyan('\n Select database:\n'));
377
+ databases.forEach((db, i) => {
378
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
379
+ });
380
+ console.log();
381
+ const answer = await question('Enter number: ');
382
+ const index = parseInt(answer) - 1;
383
+ if (isNaN(index) || index < 0 || index >= databases.length) {
384
+ console.log(chalk_1.default.red('Invalid selection'));
385
+ return;
386
+ }
387
+ dbSlug = databases[index].slug;
388
+ }
389
+ const spinner = (0, ora_1.default)('Fetching logs...').start();
390
+ try {
391
+ const response = await api_1.api.getDatabaseLogs(workspace.slug, dbSlug, tail);
392
+ spinner.stop();
393
+ console.log(chalk_1.default.cyan(`\n Database Logs (last ${tail} lines):\n`));
394
+ console.log(response.logs || 'No logs available');
395
+ console.log();
396
+ }
397
+ catch (error) {
398
+ spinner.fail(`Failed to fetch logs: ${error.message}`);
399
+ }
400
+ }
401
+ async function databaseRestart(slug) {
402
+ if (!requireAuth())
403
+ return;
404
+ if (!requireWorkspace())
405
+ return;
406
+ const workspace = (0, config_1.getCurrentWorkspace)();
407
+ let dbSlug = slug;
408
+ // If no slug provided, let user select from list
409
+ if (!dbSlug) {
410
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
411
+ const databases = await api_1.api.getDatabases(workspace.slug);
412
+ spinner.stop();
413
+ if (databases.length === 0) {
414
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
415
+ return;
416
+ }
417
+ console.log(chalk_1.default.cyan('\n Select database to restart:\n'));
418
+ databases.forEach((db, i) => {
419
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
420
+ });
421
+ console.log();
422
+ const answer = await question('Enter number: ');
423
+ const index = parseInt(answer) - 1;
424
+ if (isNaN(index) || index < 0 || index >= databases.length) {
425
+ console.log(chalk_1.default.red('Invalid selection'));
426
+ return;
427
+ }
428
+ dbSlug = databases[index].slug;
429
+ }
430
+ const confirm = await question(chalk_1.default.yellow('Are you sure you want to restart this database? (y/N): '));
431
+ if (confirm.toLowerCase() !== 'y') {
432
+ console.log(chalk_1.default.dim('Cancelled'));
433
+ return;
434
+ }
435
+ const spinner = (0, ora_1.default)('Restarting database...').start();
436
+ try {
437
+ await api_1.api.restartDatabase(workspace.slug, dbSlug);
438
+ spinner.succeed('Database restart initiated');
439
+ console.log(chalk_1.default.dim('It may take a few moments for the database to become available again.'));
440
+ }
441
+ catch (error) {
442
+ spinner.fail(`Failed to restart database: ${error.message}`);
443
+ }
444
+ }
445
+ async function databaseSize(slug) {
446
+ if (!requireAuth())
447
+ return;
448
+ if (!requireWorkspace())
449
+ return;
450
+ const workspace = (0, config_1.getCurrentWorkspace)();
451
+ let dbSlug = slug;
452
+ // If no slug provided, let user select from list
453
+ if (!dbSlug) {
454
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
455
+ const databases = await api_1.api.getDatabases(workspace.slug);
456
+ spinner.stop();
457
+ if (databases.length === 0) {
458
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
459
+ return;
460
+ }
461
+ console.log(chalk_1.default.cyan('\n Select database:\n'));
462
+ databases.forEach((db, i) => {
463
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
464
+ });
465
+ console.log();
466
+ const answer = await question('Enter number: ');
467
+ const index = parseInt(answer) - 1;
468
+ if (isNaN(index) || index < 0 || index >= databases.length) {
469
+ console.log(chalk_1.default.red('Invalid selection'));
470
+ return;
471
+ }
472
+ dbSlug = databases[index].slug;
473
+ }
474
+ const spinner = (0, ora_1.default)('Fetching database size...').start();
475
+ try {
476
+ const size = await api_1.api.getDatabaseSize(workspace.slug, dbSlug);
477
+ spinner.stop();
478
+ console.log(chalk_1.default.cyan('\n Database Size:\n'));
479
+ console.log(` ${chalk_1.default.dim('Size:')} ${size.size || 'N/A'}`);
480
+ if (size.sizeBytes) {
481
+ const mb = (size.sizeBytes / 1024 / 1024).toFixed(2);
482
+ console.log(` ${chalk_1.default.dim('Bytes:')} ${size.sizeBytes} (${mb} MB)`);
483
+ }
484
+ console.log();
485
+ }
486
+ catch (error) {
487
+ spinner.fail(`Failed to fetch database size: ${error.message}`);
488
+ }
489
+ }
490
+ async function databaseBackupList(slug) {
491
+ if (!requireAuth())
492
+ return;
493
+ if (!requireWorkspace())
494
+ return;
495
+ const workspace = (0, config_1.getCurrentWorkspace)();
496
+ let dbSlug = slug;
497
+ // If no slug provided, let user select from list
498
+ if (!dbSlug) {
499
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
500
+ const databases = await api_1.api.getDatabases(workspace.slug);
501
+ spinner.stop();
502
+ if (databases.length === 0) {
503
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
504
+ return;
505
+ }
506
+ console.log(chalk_1.default.cyan('\n Select database:\n'));
507
+ databases.forEach((db, i) => {
508
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
509
+ });
510
+ console.log();
511
+ const answer = await question('Enter number: ');
512
+ const index = parseInt(answer) - 1;
513
+ if (isNaN(index) || index < 0 || index >= databases.length) {
514
+ console.log(chalk_1.default.red('Invalid selection'));
515
+ return;
516
+ }
517
+ dbSlug = databases[index].slug;
518
+ }
519
+ const spinner = (0, ora_1.default)('Fetching backups...').start();
520
+ try {
521
+ const backups = await api_1.api.getDatabaseBackups(workspace.slug, dbSlug);
522
+ spinner.stop();
523
+ if (backups.length === 0) {
524
+ console.log(chalk_1.default.yellow('\nNo backups found. Create one with `dockup db backup create`'));
525
+ return;
526
+ }
527
+ console.log(chalk_1.default.cyan('\n Database Backups:\n'));
528
+ backups.forEach((backup, i) => {
529
+ const status = backup.status === 'completed' ? chalk_1.default.green('completed') :
530
+ backup.status === 'pending' ? chalk_1.default.yellow('pending') :
531
+ chalk_1.default.red(backup.status);
532
+ const size = backup.size ? `${(backup.size / 1024 / 1024).toFixed(2)} MB` : 'N/A';
533
+ const date = new Date(backup.createdAt).toLocaleString();
534
+ console.log(` ${i + 1}. ${chalk_1.default.white(backup.filename)} - ${status} - ${size} - ${chalk_1.default.dim(date)}`);
535
+ });
536
+ console.log();
537
+ }
538
+ catch (error) {
539
+ spinner.fail(`Failed to fetch backups: ${error.message}`);
540
+ }
541
+ }
542
+ async function databaseBackupCreate(slug) {
543
+ if (!requireAuth())
544
+ return;
545
+ if (!requireWorkspace())
546
+ return;
547
+ const workspace = (0, config_1.getCurrentWorkspace)();
548
+ let dbSlug = slug;
549
+ // If no slug provided, let user select from list
550
+ if (!dbSlug) {
551
+ const spinner = (0, ora_1.default)('Fetching databases...').start();
552
+ const databases = await api_1.api.getDatabases(workspace.slug);
553
+ spinner.stop();
554
+ if (databases.length === 0) {
555
+ console.log(chalk_1.default.yellow('No databases found in this workspace.'));
556
+ return;
557
+ }
558
+ console.log(chalk_1.default.cyan('\n Select database to backup:\n'));
559
+ databases.forEach((db, i) => {
560
+ console.log(` ${i + 1}. ${db.name} ${chalk_1.default.dim(`[${db.dbType || db.type}]`)}`);
561
+ });
562
+ console.log();
563
+ const answer = await question('Enter number: ');
564
+ const index = parseInt(answer) - 1;
565
+ if (isNaN(index) || index < 0 || index >= databases.length) {
566
+ console.log(chalk_1.default.red('Invalid selection'));
567
+ return;
568
+ }
569
+ dbSlug = databases[index].slug;
570
+ }
571
+ const spinner = (0, ora_1.default)('Creating backup...').start();
572
+ try {
573
+ const response = await api_1.api.createDatabaseBackup(workspace.slug, dbSlug);
574
+ spinner.succeed('Backup creation started');
575
+ console.log(chalk_1.default.dim(`Backup ID: ${response.backupId}`));
576
+ console.log(chalk_1.default.dim('Run `dockup db backup ls` to check the status.'));
577
+ }
578
+ catch (error) {
579
+ spinner.fail(`Failed to create backup: ${error.message}`);
580
+ if (error.message.includes('Bad Request')) {
581
+ console.log(chalk_1.default.dim('Note: Database must be running to create a backup.'));
582
+ }
583
+ }
584
+ }
@@ -0,0 +1,5 @@
1
+ export declare function envList(): Promise<void>;
2
+ export declare function envSet(keyValue: string, options: {
3
+ secret?: boolean;
4
+ }): Promise<void>;
5
+ export declare function envRemove(key: string): Promise<void>;
@@ -0,0 +1,103 @@
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.envList = envList;
7
+ exports.envSet = envSet;
8
+ exports.envRemove = envRemove;
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const ora_1 = __importDefault(require("ora"));
11
+ const config_1 = require("../lib/config");
12
+ const api_1 = require("../lib/api");
13
+ async function envList() {
14
+ if (!(0, config_1.isLoggedIn)()) {
15
+ console.log(chalk_1.default.red('Not logged in. Run `dockup login` first.'));
16
+ process.exit(1);
17
+ }
18
+ const config = (0, config_1.getProjectConfig)();
19
+ if (!config) {
20
+ console.log(chalk_1.default.red('Not linked to any service. Run `dockup link` first.'));
21
+ process.exit(1);
22
+ }
23
+ const spinner = (0, ora_1.default)('Loading environment variables...').start();
24
+ try {
25
+ const envVars = await api_1.api.getEnvVariables(config.projectSlug, config.serviceSlug);
26
+ spinner.stop();
27
+ console.log(chalk_1.default.cyan(`\n Environment variables for ${chalk_1.default.bold(config.serviceName)}\n`));
28
+ if (envVars.length === 0) {
29
+ console.log(chalk_1.default.yellow(' No environment variables set'));
30
+ console.log(chalk_1.default.dim('\n Add one with: dockup env set KEY=value\n'));
31
+ return;
32
+ }
33
+ // Find max key length for alignment
34
+ const maxKeyLen = Math.max(...envVars.map(e => e.key.length));
35
+ for (const env of envVars) {
36
+ const key = env.key.padEnd(maxKeyLen);
37
+ const value = env.isSecret ? chalk_1.default.dim('••••••••') : env.value;
38
+ const badge = env.isSecret ? chalk_1.default.yellow(' [secret]') : '';
39
+ console.log(` ${chalk_1.default.green(key)} ${value}${badge}`);
40
+ }
41
+ console.log(chalk_1.default.dim(`\n Total: ${envVars.length} variable(s)\n`));
42
+ }
43
+ catch (error) {
44
+ spinner.fail(`Failed to load environment variables: ${error.message}`);
45
+ process.exit(1);
46
+ }
47
+ }
48
+ async function envSet(keyValue, options) {
49
+ if (!(0, config_1.isLoggedIn)()) {
50
+ console.log(chalk_1.default.red('Not logged in. Run `dockup login` first.'));
51
+ process.exit(1);
52
+ }
53
+ const config = (0, config_1.getProjectConfig)();
54
+ if (!config) {
55
+ console.log(chalk_1.default.red('Not linked to any service. Run `dockup link` first.'));
56
+ process.exit(1);
57
+ }
58
+ // Parse KEY=value
59
+ const eqIndex = keyValue.indexOf('=');
60
+ if (eqIndex === -1) {
61
+ console.log(chalk_1.default.red('Invalid format. Use: dockup env set KEY=value'));
62
+ process.exit(1);
63
+ }
64
+ const key = keyValue.substring(0, eqIndex);
65
+ const value = keyValue.substring(eqIndex + 1);
66
+ if (!key) {
67
+ console.log(chalk_1.default.red('Key cannot be empty'));
68
+ process.exit(1);
69
+ }
70
+ const spinner = (0, ora_1.default)(`Setting ${key}...`).start();
71
+ try {
72
+ await api_1.api.setEnvVariable(config.projectSlug, config.serviceSlug, key, value, options.secret || false);
73
+ spinner.succeed(`Set ${chalk_1.default.green(key)}${options.secret ? chalk_1.default.yellow(' [secret]') : ''}`);
74
+ console.log(chalk_1.default.dim('\n Note: Redeploy for changes to take effect'));
75
+ console.log(chalk_1.default.dim(' Run: dockup push\n'));
76
+ }
77
+ catch (error) {
78
+ spinner.fail(`Failed to set variable: ${error.message}`);
79
+ process.exit(1);
80
+ }
81
+ }
82
+ async function envRemove(key) {
83
+ if (!(0, config_1.isLoggedIn)()) {
84
+ console.log(chalk_1.default.red('Not logged in. Run `dockup login` first.'));
85
+ process.exit(1);
86
+ }
87
+ const config = (0, config_1.getProjectConfig)();
88
+ if (!config) {
89
+ console.log(chalk_1.default.red('Not linked to any service. Run `dockup link` first.'));
90
+ process.exit(1);
91
+ }
92
+ const spinner = (0, ora_1.default)(`Removing ${key}...`).start();
93
+ try {
94
+ await api_1.api.deleteEnvVariable(config.projectSlug, config.serviceSlug, key);
95
+ spinner.succeed(`Removed ${chalk_1.default.red(key)}`);
96
+ console.log(chalk_1.default.dim('\n Note: Redeploy for changes to take effect'));
97
+ console.log(chalk_1.default.dim(' Run: dockup push\n'));
98
+ }
99
+ catch (error) {
100
+ spinner.fail(`Failed to remove variable: ${error.message}`);
101
+ process.exit(1);
102
+ }
103
+ }