@vibe-db/cli 1.0.0 → 1.1.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/bin/vibedb.js +14 -1
- package/package.json +3 -2
- package/src/api.js +34 -0
- package/src/commands/init.js +14 -5
- package/src/commands/login.js +108 -2
- package/src/commands/logout.js +47 -0
- package/src/commands/signup.js +106 -5
- package/package.json.bak +0 -35
package/bin/vibedb.js
CHANGED
|
@@ -4,6 +4,7 @@ const { Command } = require('commander');
|
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const signupCommand = require('../src/commands/signup');
|
|
6
6
|
const loginCommand = require('../src/commands/login');
|
|
7
|
+
const logoutCommand = require('../src/commands/logout');
|
|
7
8
|
const initCommand = require('../src/commands/init');
|
|
8
9
|
const listCommand = require('../src/commands/list');
|
|
9
10
|
const billingInfoCommand = require('../src/commands/billing-info');
|
|
@@ -16,7 +17,7 @@ const program = new Command();
|
|
|
16
17
|
program
|
|
17
18
|
.name('vibedb')
|
|
18
19
|
.description('VibeDB CLI - Instant database provisioning for AI-assisted development')
|
|
19
|
-
.version('1.
|
|
20
|
+
.version('1.1.0');
|
|
20
21
|
|
|
21
22
|
program
|
|
22
23
|
.command('signup')
|
|
@@ -42,6 +43,18 @@ program
|
|
|
42
43
|
}
|
|
43
44
|
});
|
|
44
45
|
|
|
46
|
+
program
|
|
47
|
+
.command('logout')
|
|
48
|
+
.description('Logout and remove saved credentials')
|
|
49
|
+
.action(async () => {
|
|
50
|
+
try {
|
|
51
|
+
await logoutCommand();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(chalk.red('Unexpected error:'), error.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
45
58
|
program
|
|
46
59
|
.command('init')
|
|
47
60
|
.description('Download VIBEDB.md prompt file to your project')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-db/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.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": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"chalk": "^4.1.2",
|
|
28
28
|
"cli-table3": "^0.6.3",
|
|
29
29
|
"commander": "^11.0.0",
|
|
30
|
-
"inquirer": "^8.2.5"
|
|
30
|
+
"inquirer": "^8.2.5",
|
|
31
|
+
"open": "^10.0.0"
|
|
31
32
|
},
|
|
32
33
|
"engines": {
|
|
33
34
|
"node": ">=18.0.0"
|
package/src/api.js
CHANGED
|
@@ -183,6 +183,38 @@ async function getInvoices(apiKey) {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Start device authorization flow
|
|
188
|
+
*/
|
|
189
|
+
async function startDeviceAuth() {
|
|
190
|
+
try {
|
|
191
|
+
const response = await axios.post(`${API_BASE_URL}/v1/auth/device`);
|
|
192
|
+
return response.data;
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (error.response) {
|
|
195
|
+
const { error: errorCode, message } = error.response.data;
|
|
196
|
+
throw new Error(message || errorCode || 'Failed to start device authorization');
|
|
197
|
+
}
|
|
198
|
+
throw new Error(`Network error: ${error.message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Poll device authorization status
|
|
204
|
+
*/
|
|
205
|
+
async function pollDeviceAuth(deviceCode) {
|
|
206
|
+
try {
|
|
207
|
+
const response = await axios.get(`${API_BASE_URL}/v1/auth/device/${deviceCode}/poll`);
|
|
208
|
+
return response.data;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error.response) {
|
|
211
|
+
const { error: errorCode, message } = error.response.data;
|
|
212
|
+
throw new Error(message || errorCode || 'Failed to poll device authorization');
|
|
213
|
+
}
|
|
214
|
+
throw new Error(`Network error: ${error.message}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
186
218
|
module.exports = {
|
|
187
219
|
signup,
|
|
188
220
|
login,
|
|
@@ -193,4 +225,6 @@ module.exports = {
|
|
|
193
225
|
createSubscription,
|
|
194
226
|
cancelSubscription,
|
|
195
227
|
getInvoices,
|
|
228
|
+
startDeviceAuth,
|
|
229
|
+
pollDeviceAuth,
|
|
196
230
|
};
|
package/src/commands/init.js
CHANGED
|
@@ -46,12 +46,21 @@ async function initCommand() {
|
|
|
46
46
|
|
|
47
47
|
console.log(chalk.green.bold('\n✓ VIBEDB.md downloaded successfully!\n'));
|
|
48
48
|
console.log(chalk.white('Location:'), chalk.cyan(promptFilePath));
|
|
49
|
-
console.log(chalk.white('API Key:'), chalk.cyan(userConfig.api_key));
|
|
50
49
|
console.log(chalk.white('Email:'), chalk.cyan(userConfig.email));
|
|
51
|
-
|
|
52
|
-
console.log(chalk.
|
|
53
|
-
console.log(chalk.gray('
|
|
54
|
-
console.log(chalk.gray('
|
|
50
|
+
|
|
51
|
+
console.log(chalk.yellow('\n⚠️ Security reminder:'));
|
|
52
|
+
console.log(chalk.gray(' • Your API key is embedded in VIBEDB.md'));
|
|
53
|
+
console.log(chalk.gray(' • Keep it secure - don\'t share or commit to public repos'));
|
|
54
|
+
console.log(chalk.gray(' • Add VIBEDB.md to .gitignore if needed'));
|
|
55
|
+
|
|
56
|
+
console.log(chalk.white('\nHow to use:'));
|
|
57
|
+
console.log(chalk.gray(' 1. Tell your AI assistant: '), chalk.cyan('"Read VIBEDB.md and provision a database"'));
|
|
58
|
+
console.log(chalk.gray(' 2. The AI will read the file and create a database for you'));
|
|
59
|
+
console.log(chalk.gray(' 3. You\'ll get connection details instantly!'));
|
|
60
|
+
|
|
61
|
+
console.log(chalk.white('\nNeed help?'));
|
|
62
|
+
console.log(chalk.gray(' • Visit: '), chalk.cyan('https://vibedb.dev/docs'));
|
|
63
|
+
console.log(chalk.gray(' • See examples in VIBEDB.md'));
|
|
55
64
|
console.log();
|
|
56
65
|
} catch (error) {
|
|
57
66
|
console.error(chalk.red.bold('\n✗ Init failed:'), chalk.red(error.message));
|
package/src/commands/login.js
CHANGED
|
@@ -3,9 +3,82 @@ const chalk = require('chalk');
|
|
|
3
3
|
const api = require('../api');
|
|
4
4
|
const config = require('../config');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
function sleep(ms) {
|
|
7
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
8
|
+
}
|
|
8
9
|
|
|
10
|
+
function formatUserCode(code) {
|
|
11
|
+
// Format as XXXX-XXXX for readability
|
|
12
|
+
return `${code.slice(0, 4)}-${code.slice(4)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function loginWithGitHub() {
|
|
16
|
+
console.log(chalk.blue('Starting GitHub authentication...\n'));
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// 1. Start device auth
|
|
20
|
+
const data = await api.startDeviceAuth();
|
|
21
|
+
const { device_code, user_code, verification_uri, interval } = data;
|
|
22
|
+
|
|
23
|
+
console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
24
|
+
console.log(chalk.cyan.bold(` Open: ${verification_uri}`));
|
|
25
|
+
console.log(chalk.yellow.bold(` Enter code: ${formatUserCode(user_code)}`));
|
|
26
|
+
console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
27
|
+
|
|
28
|
+
// Try to open browser automatically
|
|
29
|
+
try {
|
|
30
|
+
const open = (await import('open')).default;
|
|
31
|
+
await open(verification_uri);
|
|
32
|
+
console.log(chalk.gray('Opened browser automatically...\n'));
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.log(chalk.gray('Please open the URL manually\n'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(chalk.gray('Waiting for authorization...'));
|
|
38
|
+
|
|
39
|
+
// 2. Poll for completion
|
|
40
|
+
const pollInterval = (interval || 5) * 1000;
|
|
41
|
+
let attempts = 0;
|
|
42
|
+
const maxAttempts = 180 / (interval || 5); // 15 minutes / interval
|
|
43
|
+
|
|
44
|
+
while (attempts < maxAttempts) {
|
|
45
|
+
await sleep(pollInterval);
|
|
46
|
+
attempts++;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const pollData = await api.pollDeviceAuth(device_code);
|
|
50
|
+
|
|
51
|
+
if (pollData.status === 'complete') {
|
|
52
|
+
// Save API key
|
|
53
|
+
config.saveAuth(pollData.api_key, pollData.email);
|
|
54
|
+
console.log(chalk.green.bold('\n✓ Login successful!\n'));
|
|
55
|
+
console.log(chalk.white('Email:'), chalk.cyan(pollData.email));
|
|
56
|
+
console.log(chalk.gray(`API key saved to ${config.getConfigPath()}`));
|
|
57
|
+
console.log();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Still pending, continue polling
|
|
62
|
+
process.stdout.write(chalk.gray('.'));
|
|
63
|
+
} catch (err) {
|
|
64
|
+
if (err.response?.data?.error === 'authorization_expired') {
|
|
65
|
+
console.error(chalk.red.bold('\n\n✗ Authorization expired. Please try again.'));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Other errors, continue polling
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.error(chalk.red.bold('\n\n✗ Authorization timed out. Please try again.'));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(chalk.red.bold('\n✗ GitHub login failed:'), chalk.red(error.message));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function loginWithEmail() {
|
|
9
82
|
try {
|
|
10
83
|
const answers = await inquirer.prompt([
|
|
11
84
|
{
|
|
@@ -50,4 +123,37 @@ async function loginCommand() {
|
|
|
50
123
|
}
|
|
51
124
|
}
|
|
52
125
|
|
|
126
|
+
async function loginCommand() {
|
|
127
|
+
console.log(chalk.blue.bold('\n🔐 VibeDB Login\n'));
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const { method } = await inquirer.prompt([
|
|
131
|
+
{
|
|
132
|
+
type: 'list',
|
|
133
|
+
name: 'method',
|
|
134
|
+
message: 'How would you like to log in?',
|
|
135
|
+
choices: [
|
|
136
|
+
{ name: '🐙 GitHub (Recommended)', value: 'github' },
|
|
137
|
+
{ name: '📧 Email & Password', value: 'email' },
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
console.log(); // Empty line for spacing
|
|
143
|
+
|
|
144
|
+
if (method === 'github') {
|
|
145
|
+
await loginWithGitHub();
|
|
146
|
+
} else {
|
|
147
|
+
await loginWithEmail();
|
|
148
|
+
}
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (error.isTtyError) {
|
|
151
|
+
console.error(chalk.red('Prompt couldn\'t be rendered in the current environment'));
|
|
152
|
+
} else {
|
|
153
|
+
console.error(chalk.red('An unexpected error occurred:', error.message));
|
|
154
|
+
}
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
53
159
|
module.exports = loginCommand;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const config = require('../config');
|
|
5
|
+
|
|
6
|
+
async function logoutCommand() {
|
|
7
|
+
console.log(chalk.blue.bold('\n👋 VibeDB Logout\n'));
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
// Check if logged in
|
|
11
|
+
if (!config.isLoggedIn()) {
|
|
12
|
+
console.log(chalk.yellow('You are not currently logged in.'));
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const userConfig = config.readConfig();
|
|
17
|
+
|
|
18
|
+
// Confirm logout
|
|
19
|
+
const { confirm } = await inquirer.prompt([
|
|
20
|
+
{
|
|
21
|
+
type: 'confirm',
|
|
22
|
+
name: 'confirm',
|
|
23
|
+
message: `Log out of ${userConfig.email}?`,
|
|
24
|
+
default: true,
|
|
25
|
+
},
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
if (!confirm) {
|
|
29
|
+
console.log(chalk.yellow('\nLogout cancelled.'));
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Delete config file
|
|
34
|
+
const configPath = config.getConfigPath();
|
|
35
|
+
fs.unlinkSync(configPath);
|
|
36
|
+
|
|
37
|
+
console.log(chalk.green.bold('\n✓ Logged out successfully!\n'));
|
|
38
|
+
console.log(chalk.gray('Your API key has been removed from this device.'));
|
|
39
|
+
console.log(chalk.gray('To use VibeDB again, run:'), chalk.cyan('vibedb login'), chalk.gray('or'), chalk.cyan('vibedb signup'));
|
|
40
|
+
console.log();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error(chalk.red.bold('\n✗ Logout failed:'), chalk.red(error.message));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = logoutCommand;
|
package/src/commands/signup.js
CHANGED
|
@@ -3,9 +3,79 @@ const chalk = require('chalk');
|
|
|
3
3
|
const api = require('../api');
|
|
4
4
|
const config = require('../config');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
function sleep(ms) {
|
|
7
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function formatUserCode(code) {
|
|
11
|
+
return `${code.slice(0, 4)}-${code.slice(4)}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function signupWithGitHub() {
|
|
15
|
+
console.log(chalk.blue('Starting GitHub authentication...\n'));
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const data = await api.startDeviceAuth();
|
|
19
|
+
const { device_code, user_code, verification_uri, interval } = data;
|
|
20
|
+
|
|
21
|
+
console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
22
|
+
console.log(chalk.cyan.bold(` Open: ${verification_uri}`));
|
|
23
|
+
console.log(chalk.yellow.bold(` Enter code: ${formatUserCode(user_code)}`));
|
|
24
|
+
console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const open = (await import('open')).default;
|
|
28
|
+
await open(verification_uri);
|
|
29
|
+
console.log(chalk.gray('Opened browser automatically...\n'));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.log(chalk.gray('Please open the URL manually\n'));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.log(chalk.gray('Waiting for authorization...'));
|
|
35
|
+
|
|
36
|
+
const pollInterval = (interval || 5) * 1000;
|
|
37
|
+
let attempts = 0;
|
|
38
|
+
const maxAttempts = 180 / (interval || 5);
|
|
39
|
+
|
|
40
|
+
while (attempts < maxAttempts) {
|
|
41
|
+
await sleep(pollInterval);
|
|
42
|
+
attempts++;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const pollData = await api.pollDeviceAuth(device_code);
|
|
46
|
+
|
|
47
|
+
if (pollData.status === 'complete') {
|
|
48
|
+
config.saveAuth(pollData.api_key, pollData.email);
|
|
49
|
+
console.log(chalk.green.bold('\n✓ Account created successfully!\n'));
|
|
50
|
+
console.log(chalk.white('Email:'), chalk.cyan(pollData.email));
|
|
51
|
+
console.log(chalk.gray(`API key saved to ${config.getConfigPath()}`));
|
|
52
|
+
console.log(chalk.white('\nNext steps:'));
|
|
53
|
+
console.log(chalk.gray(' 1. Run'), chalk.cyan('vibedb init'), chalk.gray('to download the prompt file'));
|
|
54
|
+
console.log(chalk.gray(' 2. Add VIBEDB.md to your project'));
|
|
55
|
+
console.log(chalk.gray(' 3. Tell your AI assistant to provision a database!'));
|
|
56
|
+
console.log();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
process.stdout.write(chalk.gray('.'));
|
|
61
|
+
} catch (err) {
|
|
62
|
+
if (err.response?.data?.error === 'authorization_expired') {
|
|
63
|
+
console.error(chalk.red.bold('\n\n✗ Authorization expired. Please try again.'));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.error(chalk.red.bold('\n\n✗ Authorization timed out. Please try again.'));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(chalk.red.bold('\n✗ GitHub signup failed:'), chalk.red(error.message));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
8
77
|
|
|
78
|
+
async function signupWithEmail() {
|
|
9
79
|
try {
|
|
10
80
|
const answers = await inquirer.prompt([
|
|
11
81
|
{
|
|
@@ -52,13 +122,11 @@ async function signupCommand() {
|
|
|
52
122
|
|
|
53
123
|
const result = await api.signup(answers.email.trim().toLowerCase(), answers.password);
|
|
54
124
|
|
|
55
|
-
// Save API key to config
|
|
56
125
|
config.saveAuth(result.api_key, result.email);
|
|
57
126
|
|
|
58
127
|
console.log(chalk.green.bold('\n✓ Account created successfully!\n'));
|
|
59
128
|
console.log(chalk.white('Email:'), chalk.cyan(result.email));
|
|
60
|
-
console.log(chalk.
|
|
61
|
-
console.log(chalk.gray(`\nAPI key saved to ${config.getConfigPath()}`));
|
|
129
|
+
console.log(chalk.gray(`API key saved to ${config.getConfigPath()}`));
|
|
62
130
|
console.log(chalk.white('\nNext steps:'));
|
|
63
131
|
console.log(chalk.gray(' 1. Run'), chalk.cyan('vibedb init'), chalk.gray('to download the prompt file'));
|
|
64
132
|
console.log(chalk.gray(' 2. Add VIBEDB.md to your project'));
|
|
@@ -70,4 +138,37 @@ async function signupCommand() {
|
|
|
70
138
|
}
|
|
71
139
|
}
|
|
72
140
|
|
|
141
|
+
async function signupCommand() {
|
|
142
|
+
console.log(chalk.blue.bold('\n📝 VibeDB Signup\n'));
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const { method } = await inquirer.prompt([
|
|
146
|
+
{
|
|
147
|
+
type: 'list',
|
|
148
|
+
name: 'method',
|
|
149
|
+
message: 'How would you like to sign up?',
|
|
150
|
+
choices: [
|
|
151
|
+
{ name: '🐙 GitHub (Recommended)', value: 'github' },
|
|
152
|
+
{ name: '📧 Email & Password', value: 'email' },
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
console.log();
|
|
158
|
+
|
|
159
|
+
if (method === 'github') {
|
|
160
|
+
await signupWithGitHub();
|
|
161
|
+
} else {
|
|
162
|
+
await signupWithEmail();
|
|
163
|
+
}
|
|
164
|
+
} catch (error) {
|
|
165
|
+
if (error.isTtyError) {
|
|
166
|
+
console.error(chalk.red('Prompt couldn\'t be rendered in the current environment'));
|
|
167
|
+
} else {
|
|
168
|
+
console.error(chalk.red('An unexpected error occurred:', error.message));
|
|
169
|
+
}
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
73
174
|
module.exports = signupCommand;
|
package/package.json.bak
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@vibedb/cli",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "Command-line interface for VibeDB - instant database provisioning for AI-assisted development",
|
|
5
|
-
"main": "bin/vibedb.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"vibedb": "./bin/vibedb.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "node bin/vibedb.js --help"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"database",
|
|
14
|
-
"postgres",
|
|
15
|
-
"mysql",
|
|
16
|
-
"redis",
|
|
17
|
-
"provisioning",
|
|
18
|
-
"cli",
|
|
19
|
-
"vibedb",
|
|
20
|
-
"ai",
|
|
21
|
-
"development"
|
|
22
|
-
],
|
|
23
|
-
"author": "VibeDB",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"axios": "^1.6.0",
|
|
27
|
-
"chalk": "^4.1.2",
|
|
28
|
-
"cli-table3": "^0.6.3",
|
|
29
|
-
"commander": "^11.0.0",
|
|
30
|
-
"inquirer": "^8.2.5"
|
|
31
|
-
},
|
|
32
|
-
"engines": {
|
|
33
|
-
"node": ">=18.0.0"
|
|
34
|
-
}
|
|
35
|
-
}
|