@vibe-db/cli 1.3.0 → 1.4.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to the VibeDB CLI will be documented in this file.
4
+
5
+ ## [1.4.0] - 2026-01-12
6
+
7
+ ### Added
8
+ - **Usage Command**: New `vibedb usage` command to view storage usage and estimated costs
9
+ - Shows database storage and backup storage breakdown
10
+ - Displays estimated charges for current billing period
11
+ - Shows pricing information
12
+ - **Backup Management Commands**: Complete CLI support for backup operations
13
+ - `vibedb backup list <database_id>` - List all backups for a database
14
+ - `vibedb backup create <database_id>` - Create a manual backup
15
+ - `vibedb backup restore <database_id> <backup_id>` - Restore from backup (with confirmation)
16
+ - `vibedb backup delete <database_id> <backup_id>` - Delete a backup (with confirmation)
17
+ - Added safety confirmations for destructive operations (restore, delete)
18
+ - Improved error messages for missing authentication
19
+
20
+ ### Changed
21
+ - Enhanced API module with backup-related functions
22
+ - Updated README with comprehensive documentation for new commands
23
+
24
+ ### Fixed
25
+ - Fixed handling of undefined estimated charges in usage display
26
+
27
+ ## [1.3.0] - 2026-01-11
28
+
29
+ ### Added
30
+ - **Team Support**: Multi-team functionality
31
+ - `vibedb teams list` - List all teams
32
+ - `vibedb teams switch <team_id>` - Switch between teams
33
+ - `vibedb teams current` - Show current team
34
+ - Auto-selects personal team on login
35
+ - **Billing Commands**: Stripe billing integration
36
+ - `vibedb billing info` - View billing information
37
+ - `vibedb billing subscribe` - Subscribe to VibeDB
38
+ - `vibedb billing cancel` - Cancel subscription
39
+ - `vibedb billing invoices` - View invoices
40
+
41
+ ### Changed
42
+ - Database operations now scoped to current team
43
+ - Config file now stores current team ID
44
+
45
+ ## [1.2.0] - Earlier
46
+
47
+ ### Added
48
+ - Basic database operations
49
+ - `vibedb list` - List databases
50
+ - `vibedb init` - Download VIBEDB.md prompt file
51
+ - Authentication commands
52
+ - `vibedb signup` - Create account
53
+ - `vibedb login` - Login to existing account
54
+ - `vibedb logout` - Logout and clear credentials
55
+ - Configuration management in `~/.vibedb`
56
+
57
+ ## Future Plans
58
+
59
+ - Database creation directly from CLI
60
+ - Database deletion with recovery options
61
+ - Connection testing
62
+ - Query execution from CLI
63
+ - Import/export utilities
package/README.md CHANGED
@@ -136,6 +136,141 @@ Show currently selected team.
136
136
  **Output:**
137
137
  - Current team details (ID, name, role, type)
138
138
 
139
+ ### `vibedb usage`
140
+ Show current usage and costs.
141
+
142
+ **Requirements:**
143
+ - Must be logged in
144
+
145
+ **Output:**
146
+ - Storage breakdown (database + backup storage)
147
+ - Estimated charges for current period
148
+ - Pricing information
149
+
150
+ **Example:**
151
+ ```bash
152
+ vibedb usage
153
+
154
+ šŸ“Š Usage & Costs
155
+
156
+ Storage Usage:
157
+ Database Storage: 45.23 MB
158
+ Backup Storage: 12.67 MB
159
+ ─────────────────
160
+ Total Storage: 57.90 MB
161
+
162
+ Estimated Charges:
163
+ Current Period: $0.0823 USD
164
+
165
+ Pricing:
166
+ Storage: $0.00014 per GB-hour
167
+ Compute: $0.000167 per minute
168
+ ```
169
+
170
+ ### `vibedb backup list <database_id>`
171
+ List all backups for a database.
172
+
173
+ **Requirements:**
174
+ - Must be logged in
175
+ - Valid database ID
176
+
177
+ **Output:**
178
+ - List of backups with ID, type (auto/manual), size, and creation date
179
+
180
+ **Example:**
181
+ ```bash
182
+ vibedb backup list db_abc123
183
+
184
+ šŸ’¾ Backups
185
+
186
+ Found 3 backup(s):
187
+
188
+ 1. d4339369-a3bb-492c-afe3-2124265e9b56
189
+ Type: [Manual]
190
+ Size: 12.34 MB
191
+ Created: 1/12/2026, 8:30:06 PM
192
+
193
+ 2. a1234567-b8cd-9012-efgh-345678901234
194
+ Type: [Auto]
195
+ Size: 11.98 MB
196
+ Created: 1/12/2026, 2:00:00 AM
197
+ ```
198
+
199
+ ### `vibedb backup create <database_id>`
200
+ Create a manual backup.
201
+
202
+ **Requirements:**
203
+ - Must be logged in
204
+ - Valid database ID
205
+
206
+ **Output:**
207
+ - Backup ID and creation timestamp
208
+
209
+ **Example:**
210
+ ```bash
211
+ vibedb backup create db_abc123
212
+
213
+ āœ“ Backup created successfully!
214
+
215
+ Backup ID: d4339369-a3bb-492c-afe3-2124265e9b56
216
+ Type: [Manual]
217
+ Created: 1/12/2026, 8:30:06 PM
218
+ Size: 12.34 MB
219
+
220
+ Restore this backup with:
221
+ vibedb backup restore db_abc123 d4339369-a3bb-492c-afe3-2124265e9b56
222
+ ```
223
+
224
+ ### `vibedb backup restore <database_id> <backup_id>`
225
+ Restore a database from a backup.
226
+
227
+ **Requirements:**
228
+ - Must be logged in
229
+ - Valid database ID and backup ID
230
+ - Confirmation required (interactive)
231
+
232
+ **Warning:** This will replace ALL current data in the database!
233
+
234
+ **Example:**
235
+ ```bash
236
+ vibedb backup restore db_abc123 d4339369-a3bb-492c-afe3-2124265e9b56
237
+
238
+ šŸ”„ Restore Backup
239
+
240
+ āš ļø WARNING:
241
+ This will replace ALL current data in the database with the backup.
242
+ This action cannot be undone.
243
+
244
+ Database ID: db_abc123
245
+ Backup ID: d4339369-a3bb-492c-afe3-2124265e9b56
246
+
247
+ Are you sure you want to restore this backup? (y/N): y
248
+
249
+ āœ“ Backup restored successfully!
250
+ ```
251
+
252
+ ### `vibedb backup delete <database_id> <backup_id>`
253
+ Delete a backup.
254
+
255
+ **Requirements:**
256
+ - Must be logged in
257
+ - Valid database ID and backup ID
258
+ - Confirmation required (interactive)
259
+
260
+ **Example:**
261
+ ```bash
262
+ vibedb backup delete db_abc123 d4339369-a3bb-492c-afe3-2124265e9b56
263
+
264
+ šŸ—‘ļø Delete Backup
265
+
266
+ Database ID: db_abc123
267
+ Backup ID: d4339369-a3bb-492c-afe3-2124265e9b56
268
+
269
+ Are you sure you want to delete this backup? (y/N): y
270
+
271
+ āœ“ Backup deleted successfully!
272
+ ```
273
+
139
274
  ## Configuration
140
275
 
141
276
  The CLI stores your credentials in `~/.vibedb`:
@@ -274,7 +409,12 @@ The CLI interacts with these VibeDB API endpoints:
274
409
  - `POST /v1/auth/login` - Authenticate
275
410
  - `GET /v1/databases` - List databases
276
411
  - `GET /v1/prompt-file` - Download prompt file
277
- - `GET /v1/account` - Get account info
412
+ - `GET /v1/account` - Get account info and usage
413
+ - `GET /v1/teams` - List teams
414
+ - `GET /v1/databases/{id}/backups` - List backups
415
+ - `POST /v1/databases/{id}/backups` - Create backup
416
+ - `POST /v1/databases/{id}/backups/{backup_id}/restore` - Restore backup
417
+ - `DELETE /v1/databases/{id}/backups/{backup_id}` - Delete backup
278
418
 
279
419
  Full API docs: https://api.vibedb.dev/docs
280
420
 
package/bin/vibedb.js CHANGED
@@ -15,6 +15,11 @@ const billingInvoicesCommand = require('../src/commands/billing-invoices');
15
15
  const teamsListCommand = require('../src/commands/teams-list');
16
16
  const teamsSwitchCommand = require('../src/commands/teams-switch');
17
17
  const teamsCurrentCommand = require('../src/commands/teams-current');
18
+ const usageCommand = require('../src/commands/usage');
19
+ const backupListCommand = require('../src/commands/backup-list');
20
+ const backupCreateCommand = require('../src/commands/backup-create');
21
+ const backupRestoreCommand = require('../src/commands/backup-restore');
22
+ const backupDeleteCommand = require('../src/commands/backup-delete');
18
23
 
19
24
  const program = new Command();
20
25
 
@@ -179,6 +184,72 @@ teams
179
184
  }
180
185
  });
181
186
 
187
+ // Usage command
188
+ program
189
+ .command('usage')
190
+ .description('Show current usage and costs')
191
+ .action(async () => {
192
+ try {
193
+ await usageCommand();
194
+ } catch (error) {
195
+ console.error(chalk.red('Unexpected error:'), error.message);
196
+ process.exit(1);
197
+ }
198
+ });
199
+
200
+ // Backup commands
201
+ const backup = program
202
+ .command('backup')
203
+ .description('Manage database backups');
204
+
205
+ backup
206
+ .command('list <database_id>')
207
+ .description('List all backups for a database')
208
+ .action(async (databaseId) => {
209
+ try {
210
+ await backupListCommand(databaseId);
211
+ } catch (error) {
212
+ console.error(chalk.red('Unexpected error:'), error.message);
213
+ process.exit(1);
214
+ }
215
+ });
216
+
217
+ backup
218
+ .command('create <database_id>')
219
+ .description('Create a manual backup')
220
+ .action(async (databaseId) => {
221
+ try {
222
+ await backupCreateCommand(databaseId);
223
+ } catch (error) {
224
+ console.error(chalk.red('Unexpected error:'), error.message);
225
+ process.exit(1);
226
+ }
227
+ });
228
+
229
+ backup
230
+ .command('restore <database_id> <backup_id>')
231
+ .description('Restore a database from a backup')
232
+ .action(async (databaseId, backupId) => {
233
+ try {
234
+ await backupRestoreCommand(databaseId, backupId);
235
+ } catch (error) {
236
+ console.error(chalk.red('Unexpected error:'), error.message);
237
+ process.exit(1);
238
+ }
239
+ });
240
+
241
+ backup
242
+ .command('delete <database_id> <backup_id>')
243
+ .description('Delete a backup')
244
+ .action(async (databaseId, backupId) => {
245
+ try {
246
+ await backupDeleteCommand(databaseId, backupId);
247
+ } catch (error) {
248
+ console.error(chalk.red('Unexpected error:'), error.message);
249
+ process.exit(1);
250
+ }
251
+ });
252
+
182
253
  // Global error handler
183
254
  process.on('unhandledRejection', (error) => {
184
255
  console.error(chalk.red.bold('\nāœ— Unhandled error:'), error.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-db/cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Command-line interface for VibeDB - instant database provisioning for AI-assisted development",
5
5
  "main": "bin/vibedb.js",
6
6
  "bin": {
package/src/api.js CHANGED
@@ -263,6 +263,97 @@ async function getTeam(apiKey, teamId) {
263
263
  }
264
264
  }
265
265
 
266
+ /**
267
+ * List backups for a database
268
+ */
269
+ async function listBackups(apiKey, databaseId) {
270
+ try {
271
+ const response = await axios.get(`${API_BASE_URL}/v1/databases/${databaseId}/backups`, {
272
+ headers: {
273
+ Authorization: `Bearer ${apiKey}`,
274
+ },
275
+ });
276
+ return response.data.backups || [];
277
+ } catch (error) {
278
+ if (error.response) {
279
+ const { error: errorCode, message } = error.response.data;
280
+ throw new Error(message || errorCode || 'Failed to list backups');
281
+ }
282
+ throw new Error(`Network error: ${error.message}`);
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Create a backup for a database
288
+ */
289
+ async function createBackup(apiKey, databaseId) {
290
+ try {
291
+ const response = await axios.post(
292
+ `${API_BASE_URL}/v1/databases/${databaseId}/backups`,
293
+ {},
294
+ {
295
+ headers: {
296
+ Authorization: `Bearer ${apiKey}`,
297
+ },
298
+ }
299
+ );
300
+ return response.data;
301
+ } catch (error) {
302
+ if (error.response) {
303
+ const { error: errorCode, message } = error.response.data;
304
+ throw new Error(message || errorCode || 'Failed to create backup');
305
+ }
306
+ throw new Error(`Network error: ${error.message}`);
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Restore a database from a backup
312
+ */
313
+ async function restoreBackup(apiKey, databaseId, backupId) {
314
+ try {
315
+ const response = await axios.post(
316
+ `${API_BASE_URL}/v1/databases/${databaseId}/backups/${backupId}/restore`,
317
+ {},
318
+ {
319
+ headers: {
320
+ Authorization: `Bearer ${apiKey}`,
321
+ },
322
+ }
323
+ );
324
+ return response.data;
325
+ } catch (error) {
326
+ if (error.response) {
327
+ const { error: errorCode, message } = error.response.data;
328
+ throw new Error(message || errorCode || 'Failed to restore backup');
329
+ }
330
+ throw new Error(`Network error: ${error.message}`);
331
+ }
332
+ }
333
+
334
+ /**
335
+ * Delete a backup
336
+ */
337
+ async function deleteBackup(apiKey, databaseId, backupId) {
338
+ try {
339
+ const response = await axios.delete(
340
+ `${API_BASE_URL}/v1/databases/${databaseId}/backups/${backupId}`,
341
+ {
342
+ headers: {
343
+ Authorization: `Bearer ${apiKey}`,
344
+ },
345
+ }
346
+ );
347
+ return response.data;
348
+ } catch (error) {
349
+ if (error.response) {
350
+ const { error: errorCode, message } = error.response.data;
351
+ throw new Error(message || errorCode || 'Failed to delete backup');
352
+ }
353
+ throw new Error(`Network error: ${error.message}`);
354
+ }
355
+ }
356
+
266
357
  module.exports = {
267
358
  signup,
268
359
  login,
@@ -277,4 +368,8 @@ module.exports = {
277
368
  pollDeviceAuth,
278
369
  listTeams,
279
370
  getTeam,
371
+ listBackups,
372
+ createBackup,
373
+ restoreBackup,
374
+ deleteBackup,
280
375
  };
@@ -0,0 +1,48 @@
1
+ const chalk = require('chalk');
2
+ const api = require('../api');
3
+ const config = require('../config');
4
+
5
+ async function backupCreateCommand(databaseId) {
6
+ console.log(chalk.blue.bold('\nšŸ’¾ Create Backup\n'));
7
+
8
+ try {
9
+ // Check if logged in
10
+ if (!config.isLoggedIn()) {
11
+ console.error(chalk.red.bold('āœ— Not logged in'));
12
+ console.log(chalk.gray('\nPlease run'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'), chalk.gray('first.'));
13
+ process.exit(1);
14
+ }
15
+
16
+ if (!databaseId) {
17
+ console.error(chalk.red.bold('āœ— Database ID is required'));
18
+ console.log(chalk.gray('\nUsage:'), chalk.cyan('vibedb backup create <database-id>'));
19
+ process.exit(1);
20
+ }
21
+
22
+ const apiKey = config.getAPIKey();
23
+
24
+ console.log(chalk.gray(`Creating backup for database ${databaseId}...`));
25
+
26
+ const backup = await api.createBackup(apiKey, databaseId);
27
+
28
+ console.log(chalk.green.bold('\nāœ“ Backup created successfully!\n'));
29
+ console.log(chalk.gray('Backup ID:'), chalk.cyan(backup.id));
30
+ console.log(chalk.gray('Type:'), chalk.green('[Manual]'));
31
+ console.log(chalk.gray('Created:'), chalk.white(new Date(backup.created_at).toLocaleString()));
32
+
33
+ if (backup.size_mb) {
34
+ console.log(chalk.gray('Size:'), chalk.cyan(`${backup.size_mb.toFixed(2)} MB`));
35
+ }
36
+
37
+ console.log();
38
+ console.log(chalk.gray('Restore this backup with:'));
39
+ console.log(chalk.cyan(`vibedb backup restore ${databaseId} ${backup.id}`));
40
+ console.log();
41
+
42
+ } catch (error) {
43
+ console.error(chalk.red.bold('\nāœ— Failed to create backup:'), chalk.red(error.message));
44
+ process.exit(1);
45
+ }
46
+ }
47
+
48
+ module.exports = backupCreateCommand;
@@ -0,0 +1,64 @@
1
+ const chalk = require('chalk');
2
+ const readline = require('readline');
3
+ const api = require('../api');
4
+ const config = require('../config');
5
+
6
+ async function askConfirmation(question) {
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout,
10
+ });
11
+
12
+ return new Promise((resolve) => {
13
+ rl.question(question, (answer) => {
14
+ rl.close();
15
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
16
+ });
17
+ });
18
+ }
19
+
20
+ async function backupDeleteCommand(databaseId, backupId) {
21
+ console.log(chalk.blue.bold('\nšŸ—‘ļø Delete Backup\n'));
22
+
23
+ try {
24
+ // Check if logged in
25
+ if (!config.isLoggedIn()) {
26
+ console.error(chalk.red.bold('āœ— Not logged in'));
27
+ console.log(chalk.gray('\nPlease run'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'), chalk.gray('first.'));
28
+ process.exit(1);
29
+ }
30
+
31
+ if (!databaseId || !backupId) {
32
+ console.error(chalk.red.bold('āœ— Database ID and Backup ID are required'));
33
+ console.log(chalk.gray('\nUsage:'), chalk.cyan('vibedb backup delete <database-id> <backup-id>'));
34
+ process.exit(1);
35
+ }
36
+
37
+ const apiKey = config.getAPIKey();
38
+
39
+ console.log(chalk.gray('Database ID:'), chalk.cyan(databaseId));
40
+ console.log(chalk.gray('Backup ID:'), chalk.cyan(backupId));
41
+ console.log();
42
+
43
+ const confirmed = await askConfirmation(chalk.white('Are you sure you want to delete this backup? (y/N): '));
44
+
45
+ if (!confirmed) {
46
+ console.log(chalk.gray('\nDeletion cancelled.'));
47
+ return;
48
+ }
49
+
50
+ console.log(chalk.gray('\nDeleting backup...'));
51
+
52
+ await api.deleteBackup(apiKey, databaseId, backupId);
53
+
54
+ console.log(chalk.green.bold('\nāœ“ Backup deleted successfully!\n'));
55
+ console.log(chalk.gray('Backup ID:'), chalk.cyan(backupId));
56
+ console.log();
57
+
58
+ } catch (error) {
59
+ console.error(chalk.red.bold('\nāœ— Failed to delete backup:'), chalk.red(error.message));
60
+ process.exit(1);
61
+ }
62
+ }
63
+
64
+ module.exports = backupDeleteCommand;
@@ -0,0 +1,67 @@
1
+ const chalk = require('chalk');
2
+ const api = require('../api');
3
+ const config = require('../config');
4
+
5
+ async function backupListCommand(databaseId) {
6
+ console.log(chalk.blue.bold('\nšŸ’¾ Backups\n'));
7
+
8
+ try {
9
+ // Check if logged in
10
+ if (!config.isLoggedIn()) {
11
+ console.error(chalk.red.bold('āœ— Not logged in'));
12
+ console.log(chalk.gray('\nPlease run'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'), chalk.gray('first.'));
13
+ process.exit(1);
14
+ }
15
+
16
+ if (!databaseId) {
17
+ console.error(chalk.red.bold('āœ— Database ID is required'));
18
+ console.log(chalk.gray('\nUsage:'), chalk.cyan('vibedb backup list <database-id>'));
19
+ process.exit(1);
20
+ }
21
+
22
+ const apiKey = config.getAPIKey();
23
+
24
+ console.log(chalk.gray(`Fetching backups for database ${databaseId}...`));
25
+
26
+ const backups = await api.listBackups(apiKey, databaseId);
27
+
28
+ if (backups.length === 0) {
29
+ console.log(chalk.yellow('\nNo backups found for this database.'));
30
+ console.log(chalk.gray('Create one with:'), chalk.cyan(`vibedb backup create ${databaseId}`));
31
+ return;
32
+ }
33
+
34
+ console.log();
35
+ console.log(chalk.gray(`Found ${backups.length} backup(s):\n`));
36
+
37
+ // Display backups in a table format
38
+ backups.forEach((backup, index) => {
39
+ const isAutomatic = backup.type === 'automatic';
40
+ const typeLabel = isAutomatic ? chalk.blue('[Auto]') : chalk.green('[Manual]');
41
+ const sizeLabel = backup.size_mb ? `${backup.size_mb.toFixed(2)} MB` : 'N/A';
42
+ const createdAt = new Date(backup.created_at).toLocaleString();
43
+
44
+ console.log(chalk.white.bold(`${index + 1}. ${backup.id}`));
45
+ console.log(chalk.gray(' Type:'), typeLabel);
46
+ console.log(chalk.gray(' Size:'), chalk.cyan(sizeLabel));
47
+ console.log(chalk.gray(' Created:'), chalk.white(createdAt));
48
+
49
+ if (backup.deleted_at) {
50
+ console.log(chalk.gray(' Status:'), chalk.red('Deleted'));
51
+ }
52
+
53
+ console.log();
54
+ });
55
+
56
+ console.log(chalk.gray('Commands:'));
57
+ console.log(chalk.gray(' Restore:'), chalk.cyan(`vibedb backup restore ${databaseId} <backup-id>`));
58
+ console.log(chalk.gray(' Delete:'), chalk.cyan(`vibedb backup delete ${databaseId} <backup-id>`));
59
+ console.log();
60
+
61
+ } catch (error) {
62
+ console.error(chalk.red.bold('\nāœ— Failed to list backups:'), chalk.red(error.message));
63
+ process.exit(1);
64
+ }
65
+ }
66
+
67
+ module.exports = backupListCommand;
@@ -0,0 +1,73 @@
1
+ const chalk = require('chalk');
2
+ const readline = require('readline');
3
+ const api = require('../api');
4
+ const config = require('../config');
5
+
6
+ async function askConfirmation(question) {
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout,
10
+ });
11
+
12
+ return new Promise((resolve) => {
13
+ rl.question(question, (answer) => {
14
+ rl.close();
15
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
16
+ });
17
+ });
18
+ }
19
+
20
+ async function backupRestoreCommand(databaseId, backupId) {
21
+ console.log(chalk.blue.bold('\nšŸ”„ Restore Backup\n'));
22
+
23
+ try {
24
+ // Check if logged in
25
+ if (!config.isLoggedIn()) {
26
+ console.error(chalk.red.bold('āœ— Not logged in'));
27
+ console.log(chalk.gray('\nPlease run'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'), chalk.gray('first.'));
28
+ process.exit(1);
29
+ }
30
+
31
+ if (!databaseId || !backupId) {
32
+ console.error(chalk.red.bold('āœ— Database ID and Backup ID are required'));
33
+ console.log(chalk.gray('\nUsage:'), chalk.cyan('vibedb backup restore <database-id> <backup-id>'));
34
+ process.exit(1);
35
+ }
36
+
37
+ const apiKey = config.getAPIKey();
38
+
39
+ // Warning message
40
+ console.log(chalk.yellow.bold('āš ļø WARNING:'));
41
+ console.log(chalk.yellow('This will replace ALL current data in the database with the backup.'));
42
+ console.log(chalk.yellow('This action cannot be undone.\n'));
43
+
44
+ console.log(chalk.gray('Database ID:'), chalk.cyan(databaseId));
45
+ console.log(chalk.gray('Backup ID:'), chalk.cyan(backupId));
46
+ console.log();
47
+
48
+ const confirmed = await askConfirmation(chalk.white('Are you sure you want to restore this backup? (y/N): '));
49
+
50
+ if (!confirmed) {
51
+ console.log(chalk.gray('\nRestore cancelled.'));
52
+ return;
53
+ }
54
+
55
+ console.log(chalk.gray('\nRestoring backup...'));
56
+
57
+ const result = await api.restoreBackup(apiKey, databaseId, backupId);
58
+
59
+ console.log(chalk.green.bold('\nāœ“ Backup restored successfully!\n'));
60
+ console.log(chalk.gray('Database ID:'), chalk.cyan(databaseId));
61
+ console.log(chalk.gray('Backup ID:'), chalk.cyan(backupId));
62
+ console.log(chalk.gray('Restored at:'), chalk.white(new Date().toLocaleString()));
63
+ console.log();
64
+ console.log(chalk.green('Your database has been restored to the backup state.'));
65
+ console.log();
66
+
67
+ } catch (error) {
68
+ console.error(chalk.red.bold('\nāœ— Failed to restore backup:'), chalk.red(error.message));
69
+ process.exit(1);
70
+ }
71
+ }
72
+
73
+ module.exports = backupRestoreCommand;
@@ -0,0 +1,66 @@
1
+ const chalk = require('chalk');
2
+ const api = require('../api');
3
+ const config = require('../config');
4
+
5
+ async function usageCommand() {
6
+ console.log(chalk.blue.bold('\nšŸ“Š Usage & Costs\n'));
7
+
8
+ try {
9
+ // Check if logged in
10
+ if (!config.isLoggedIn()) {
11
+ console.error(chalk.red.bold('āœ— Not logged in'));
12
+ console.log(chalk.gray('\nPlease run'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'), chalk.gray('first.'));
13
+ process.exit(1);
14
+ }
15
+
16
+ const apiKey = config.getAPIKey();
17
+ const currentTeamId = config.getCurrentTeamId();
18
+
19
+ console.log(chalk.gray('Fetching usage data...'));
20
+
21
+ const account = await api.getAccount(apiKey, currentTeamId);
22
+
23
+ console.log();
24
+
25
+ // Storage breakdown
26
+ console.log(chalk.white.bold('Storage Usage:'));
27
+
28
+ if (account.storage_breakdown) {
29
+ const { database_storage_mb, backup_storage_mb, total_storage_mb } = account.storage_breakdown;
30
+
31
+ console.log(chalk.gray(' Database Storage:'), chalk.white(`${database_storage_mb.toFixed(2)} MB`));
32
+ console.log(chalk.gray(' Backup Storage:'), chalk.white(`${backup_storage_mb.toFixed(2)} MB`));
33
+ console.log(chalk.gray(' ─────────────────'));
34
+ console.log(chalk.gray(' Total Storage:'), chalk.cyan.bold(`${total_storage_mb.toFixed(2)} MB`));
35
+ } else {
36
+ console.log(chalk.gray(' Total Storage:'), chalk.cyan.bold(`${account.storage_total_mb.toFixed(2)} MB`));
37
+ }
38
+
39
+ console.log();
40
+
41
+ // Cost information
42
+ console.log(chalk.white.bold('Estimated Charges:'));
43
+ const charges = account.estimated_charges_usd || 0;
44
+ console.log(chalk.gray(' Current Period:'), chalk.green.bold(`$${charges.toFixed(4)} USD`));
45
+ console.log();
46
+
47
+ // Pricing info
48
+ console.log(chalk.gray('Pricing:'));
49
+ console.log(chalk.gray(' Storage: $0.00014 per GB-hour'));
50
+ console.log(chalk.gray(' Compute: $0.000167 per minute'));
51
+ console.log();
52
+
53
+ // Show current team if applicable
54
+ if (currentTeamId) {
55
+ console.log(chalk.gray('Team:'), chalk.cyan(currentTeamId));
56
+ console.log(chalk.gray('Run'), chalk.cyan('vibedb teams list'), chalk.gray('to see all your teams.'));
57
+ console.log();
58
+ }
59
+
60
+ } catch (error) {
61
+ console.error(chalk.red.bold('\nāœ— Failed to fetch usage:'), chalk.red(error.message));
62
+ process.exit(1);
63
+ }
64
+ }
65
+
66
+ module.exports = usageCommand;