mozhost-cli 2.0.1 → 2.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/mozhost.js +61 -4
- package/package.json +1 -1
- package/src/commands/databases.js +389 -0
- package/src/utils/api.js +33 -0
package/bin/mozhost.js
CHANGED
|
@@ -5,6 +5,7 @@ const chalk = require('chalk');
|
|
|
5
5
|
const authCommands = require('../src/commands/auth');
|
|
6
6
|
const containerCommands = require('../src/commands/containers');
|
|
7
7
|
const deployCommands = require('../src/commands/deploy');
|
|
8
|
+
const databaseCommands = require('../src/commands/databases'); // 👈 NOVO
|
|
8
9
|
const packageJson = require('../package.json');
|
|
9
10
|
|
|
10
11
|
program
|
|
@@ -12,7 +13,9 @@ program
|
|
|
12
13
|
.description('CLI for MozHost - Hospedagem de Bots e APIs')
|
|
13
14
|
.version(packageJson.version);
|
|
14
15
|
|
|
15
|
-
//
|
|
16
|
+
// ============================================
|
|
17
|
+
// AUTH COMMANDS
|
|
18
|
+
// ============================================
|
|
16
19
|
program
|
|
17
20
|
.command('auth')
|
|
18
21
|
.description('Autenticar na MozHost')
|
|
@@ -28,7 +31,9 @@ program
|
|
|
28
31
|
.description('Ver usuário atual')
|
|
29
32
|
.action(authCommands.whoami);
|
|
30
33
|
|
|
31
|
-
//
|
|
34
|
+
// ============================================
|
|
35
|
+
// CONTAINER COMMANDS
|
|
36
|
+
// ============================================
|
|
32
37
|
program
|
|
33
38
|
.command('containers')
|
|
34
39
|
.alias('ls')
|
|
@@ -79,7 +84,48 @@ program
|
|
|
79
84
|
.description('Ver URL do container')
|
|
80
85
|
.action(containerCommands.url);
|
|
81
86
|
|
|
82
|
-
//
|
|
87
|
+
// ============================================
|
|
88
|
+
// DATABASE COMMANDS 👈 NOVO
|
|
89
|
+
// ============================================
|
|
90
|
+
program
|
|
91
|
+
.command('db:list')
|
|
92
|
+
.alias('db:ls')
|
|
93
|
+
.description('Listar databases')
|
|
94
|
+
.action(databaseCommands.list);
|
|
95
|
+
|
|
96
|
+
program
|
|
97
|
+
.command('db:create')
|
|
98
|
+
.description('Criar novo database')
|
|
99
|
+
.requiredOption('-n, --name <name>', 'Nome do database')
|
|
100
|
+
.requiredOption('-t, --type <type>', 'Tipo (mysql, mariadb, postgres, mongodb, redis)')
|
|
101
|
+
.option('-c, --container <container>', 'Container para vincular (opcional)')
|
|
102
|
+
.action(databaseCommands.create);
|
|
103
|
+
|
|
104
|
+
program
|
|
105
|
+
.command('db:info <database>')
|
|
106
|
+
.description('Ver informações detalhadas do database')
|
|
107
|
+
.action(databaseCommands.info);
|
|
108
|
+
|
|
109
|
+
program
|
|
110
|
+
.command('db:credentials <database>')
|
|
111
|
+
.alias('db:creds')
|
|
112
|
+
.description('Ver credenciais do database')
|
|
113
|
+
.action(databaseCommands.credentials);
|
|
114
|
+
|
|
115
|
+
program
|
|
116
|
+
.command('db:link <database> <container>')
|
|
117
|
+
.description('Vincular database a um container')
|
|
118
|
+
.action(databaseCommands.link);
|
|
119
|
+
|
|
120
|
+
program
|
|
121
|
+
.command('db:delete <database>')
|
|
122
|
+
.alias('db:rm')
|
|
123
|
+
.description('Deletar database')
|
|
124
|
+
.action(databaseCommands.deleteDatabase);
|
|
125
|
+
|
|
126
|
+
// ============================================
|
|
127
|
+
// DEPLOY COMMANDS
|
|
128
|
+
// ============================================
|
|
83
129
|
program
|
|
84
130
|
.command('init')
|
|
85
131
|
.description('Inicializar projeto para deploy')
|
|
@@ -96,11 +142,22 @@ program
|
|
|
96
142
|
.description('Vincular diretório atual a um container')
|
|
97
143
|
.action(deployCommands.link);
|
|
98
144
|
|
|
99
|
-
//
|
|
145
|
+
// ============================================
|
|
146
|
+
// PARSE & HELP
|
|
147
|
+
// ============================================
|
|
100
148
|
program.parse(process.argv);
|
|
101
149
|
|
|
102
150
|
// Show help if no command
|
|
103
151
|
if (!process.argv.slice(2).length) {
|
|
104
152
|
console.log(chalk.cyan.bold('\n🚀 MozHost CLI\n'));
|
|
105
153
|
program.outputHelp();
|
|
154
|
+
|
|
155
|
+
// Mostrar exemplos úteis
|
|
156
|
+
console.log(chalk.gray('\nExemplos:'));
|
|
157
|
+
console.log(chalk.white(' mozhost auth # Autenticar'));
|
|
158
|
+
console.log(chalk.white(' mozhost ls # Listar containers'));
|
|
159
|
+
console.log(chalk.white(' mozhost create -n app -t nodejs # Criar container'));
|
|
160
|
+
console.log(chalk.white(' mozhost db:list # Listar databases'));
|
|
161
|
+
console.log(chalk.white(' mozhost db:create -n db -t mysql # Criar database'));
|
|
162
|
+
console.log();
|
|
106
163
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const api = require('../utils/api');
|
|
5
|
+
|
|
6
|
+
// ============================================
|
|
7
|
+
// HELPER FUNCTION - Resolver Nome ou ID
|
|
8
|
+
// ============================================
|
|
9
|
+
async function resolveDatabase(identifier) {
|
|
10
|
+
try {
|
|
11
|
+
// Tenta buscar diretamente por ID
|
|
12
|
+
const response = await api.getDatabase(identifier);
|
|
13
|
+
return response.database;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
// Se não encontrar (404), busca na lista por nome
|
|
16
|
+
if (error.response?.status === 404 || error.response?.data?.error?.includes('not found')) {
|
|
17
|
+
const listResponse = await api.listDatabases();
|
|
18
|
+
|
|
19
|
+
// Procura por nome, ID completo ou ID parcial
|
|
20
|
+
const found = listResponse.databases.find(d =>
|
|
21
|
+
d.name === identifier ||
|
|
22
|
+
d.id === identifier ||
|
|
23
|
+
d.id.startsWith(identifier)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (!found) {
|
|
27
|
+
// Procura databases similares para sugerir
|
|
28
|
+
const similar = listResponse.databases.filter(d =>
|
|
29
|
+
d.name.toLowerCase().includes(identifier.toLowerCase()) ||
|
|
30
|
+
d.id.includes(identifier)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (similar.length > 0) {
|
|
34
|
+
console.log(chalk.yellow('\n💡 Você quis dizer:'));
|
|
35
|
+
similar.forEach(d => {
|
|
36
|
+
console.log(chalk.white(` • ${d.name} ${chalk.gray(`(${d.id.slice(0, 8)}) - ${d.type}`)}`));
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
console.log(chalk.gray('\n💡 Use: mozhost db:list para ver todos os databases'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new Error(`Database "${identifier}" não encontrado`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return found;
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ============================================
|
|
52
|
+
// LIST - Listar todos os databases
|
|
53
|
+
// ============================================
|
|
54
|
+
async function list() {
|
|
55
|
+
try {
|
|
56
|
+
const spinner = ora('Carregando databases...').start();
|
|
57
|
+
|
|
58
|
+
const response = await api.listDatabases();
|
|
59
|
+
|
|
60
|
+
spinner.stop();
|
|
61
|
+
|
|
62
|
+
if (response.databases.length === 0) {
|
|
63
|
+
console.log(chalk.yellow('\n⚠️ Nenhum database encontrado'));
|
|
64
|
+
console.log(chalk.gray(' Use: mozhost db:create --name <nome> --type <tipo>'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
console.log(chalk.cyan.bold(`\n💾 Databases (${response.databases.length})\n`));
|
|
69
|
+
|
|
70
|
+
response.databases.forEach(database => {
|
|
71
|
+
const statusColor = database.status === 'running' ? chalk.green : chalk.gray;
|
|
72
|
+
const statusIcon = database.status === 'running' ? '●' : '○';
|
|
73
|
+
|
|
74
|
+
// Ícones por tipo de database
|
|
75
|
+
const typeIcons = {
|
|
76
|
+
mysql: '🐬',
|
|
77
|
+
mariadb: '🦭',
|
|
78
|
+
postgres: '🐘',
|
|
79
|
+
mongodb: '🍃',
|
|
80
|
+
redis: '🔴'
|
|
81
|
+
};
|
|
82
|
+
const typeIcon = typeIcons[database.type] || '💾';
|
|
83
|
+
|
|
84
|
+
console.log(`${statusColor(statusIcon)} ${typeIcon} ${chalk.white.bold(database.name)} ${chalk.gray(`(${database.id.slice(0, 8)})`)}`);
|
|
85
|
+
console.log(` ${chalk.gray('Tipo:')} ${database.type}`);
|
|
86
|
+
console.log(` ${chalk.gray('Status:')} ${statusColor(database.status)}`);
|
|
87
|
+
console.log(` ${chalk.gray('Host:')} ${chalk.cyan(database.host)}`);
|
|
88
|
+
console.log(` ${chalk.gray('Porta:')} ${database.port}`);
|
|
89
|
+
console.log(` ${chalk.gray('Database:')} ${database.database_name}`);
|
|
90
|
+
|
|
91
|
+
if (database.containers && database.containers.length > 0) {
|
|
92
|
+
console.log(` ${chalk.gray('Containers:')} ${database.containers.join(', ')}`);
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (response.total_cost !== undefined) {
|
|
98
|
+
console.log(chalk.yellow(`💰 Custo total: ${response.total_cost} coins/dia\n`));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(chalk.red('\n❌ Erro ao listar databases:'));
|
|
103
|
+
console.error(chalk.red(` ${error.response?.data?.error || error.message}`));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ============================================
|
|
109
|
+
// CREATE - Criar novo database
|
|
110
|
+
// ============================================
|
|
111
|
+
async function create(options) {
|
|
112
|
+
try {
|
|
113
|
+
const { name, type, container } = options;
|
|
114
|
+
|
|
115
|
+
if (!name || !type) {
|
|
116
|
+
console.error(chalk.red('❌ Nome e tipo são obrigatórios'));
|
|
117
|
+
console.log(chalk.gray(' Use: mozhost db:create --name <nome> --type <tipo>'));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const validTypes = ['mysql', 'mariadb', 'postgres', 'mongodb', 'redis'];
|
|
122
|
+
if (!validTypes.includes(type)) {
|
|
123
|
+
console.error(chalk.red('❌ Tipo inválido'));
|
|
124
|
+
console.log(chalk.gray(' Tipos válidos: mysql, mariadb, postgres, mongodb, redis'));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
console.log(chalk.cyan.bold('\n🔨 Criando database...\n'));
|
|
129
|
+
console.log(chalk.gray(` Nome: ${name}`));
|
|
130
|
+
console.log(chalk.gray(` Tipo: ${type}`));
|
|
131
|
+
if (container) {
|
|
132
|
+
console.log(chalk.gray(` Container: ${container}`));
|
|
133
|
+
}
|
|
134
|
+
console.log();
|
|
135
|
+
|
|
136
|
+
const spinner = ora('Criando database...').start();
|
|
137
|
+
|
|
138
|
+
const response = await api.createDatabase({ name, type, container });
|
|
139
|
+
|
|
140
|
+
spinner.succeed(chalk.green('✅ Database criado com sucesso!'));
|
|
141
|
+
|
|
142
|
+
const db = response.database;
|
|
143
|
+
|
|
144
|
+
console.log(chalk.gray('\n📋 Informações do Database:'));
|
|
145
|
+
console.log(chalk.white(` ID: ${db.id}`));
|
|
146
|
+
console.log(chalk.white(` Nome: ${db.name}`));
|
|
147
|
+
console.log(chalk.white(` Tipo: ${db.type}`));
|
|
148
|
+
console.log(chalk.white(` Status: ${db.status}`));
|
|
149
|
+
console.log(chalk.cyan(` Host: ${db.host}`));
|
|
150
|
+
console.log(chalk.white(` Porta: ${db.port}`));
|
|
151
|
+
console.log(chalk.white(` Database: ${db.database_name}`));
|
|
152
|
+
console.log(chalk.white(` Username: ${db.username}`));
|
|
153
|
+
console.log(chalk.yellow(` Password: ${db.password}`));
|
|
154
|
+
console.log(chalk.yellow(` 💰 Custo: ${db.cost} coins/dia`));
|
|
155
|
+
|
|
156
|
+
console.log(chalk.gray('\n🔗 Connection String:'));
|
|
157
|
+
console.log(chalk.cyan(` ${db.connection_string}`));
|
|
158
|
+
|
|
159
|
+
console.log(chalk.gray('\n💡 Dicas:'));
|
|
160
|
+
console.log(chalk.white(` • Guarde a senha em local seguro`));
|
|
161
|
+
console.log(chalk.white(` • Use: mozhost db:credentials ${db.name} para ver novamente`));
|
|
162
|
+
if (!container) {
|
|
163
|
+
console.log(chalk.white(` • Use: mozhost db:link ${db.name} <container> para vincular`));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(chalk.red('\n❌ Erro ao criar database:'));
|
|
168
|
+
|
|
169
|
+
if (error.response?.data) {
|
|
170
|
+
console.error(chalk.red(` ${error.response.data.error || error.response.data.message}`));
|
|
171
|
+
|
|
172
|
+
if (error.response.status === 400 && error.response.data.error?.includes('Insufficient coins')) {
|
|
173
|
+
console.log(chalk.yellow('\n💡 Dica: Você não tem coins suficientes (necessário: 5 coins)'));
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
console.error(chalk.red(` ${error.message}`));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ============================================
|
|
184
|
+
// INFO - Informações detalhadas do database
|
|
185
|
+
// ============================================
|
|
186
|
+
async function info(identifier) {
|
|
187
|
+
try {
|
|
188
|
+
const spinner = ora('Resolvendo database...').start();
|
|
189
|
+
const database = await resolveDatabase(identifier);
|
|
190
|
+
|
|
191
|
+
spinner.text = `Carregando informações de ${database.name}...`;
|
|
192
|
+
|
|
193
|
+
// Busca detalhes completos
|
|
194
|
+
const response = await api.getDatabase(database.id);
|
|
195
|
+
spinner.stop();
|
|
196
|
+
|
|
197
|
+
const db = response.database;
|
|
198
|
+
|
|
199
|
+
// Ícones por tipo
|
|
200
|
+
const typeIcons = {
|
|
201
|
+
mysql: '🐬',
|
|
202
|
+
mariadb: '🦭',
|
|
203
|
+
postgres: '🐘',
|
|
204
|
+
mongodb: '🍃',
|
|
205
|
+
redis: '🔴'
|
|
206
|
+
};
|
|
207
|
+
const typeIcon = typeIcons[db.type] || '💾';
|
|
208
|
+
|
|
209
|
+
console.log(chalk.cyan.bold(`\n${typeIcon} Informações do Database\n`));
|
|
210
|
+
console.log(chalk.white(` ID: ${db.id}`));
|
|
211
|
+
console.log(chalk.white(` Nome: ${db.name}`));
|
|
212
|
+
console.log(chalk.white(` Tipo: ${db.type}`));
|
|
213
|
+
|
|
214
|
+
const statusColor = db.status === 'running' ? chalk.green : chalk.gray;
|
|
215
|
+
console.log(` Status: ${statusColor(db.status)}`);
|
|
216
|
+
|
|
217
|
+
console.log(chalk.cyan(` Host: ${db.host}`));
|
|
218
|
+
console.log(chalk.white(` Porta: ${db.port}`));
|
|
219
|
+
console.log(chalk.white(` Database: ${db.database_name}`));
|
|
220
|
+
console.log(chalk.white(` Username: ${db.username}`));
|
|
221
|
+
console.log(chalk.yellow(` Password: ${db.password}`));
|
|
222
|
+
console.log(chalk.yellow(` 💰 Custo: ${db.cost} coins/dia`));
|
|
223
|
+
|
|
224
|
+
if (db.containers && db.containers.length > 0) {
|
|
225
|
+
console.log(chalk.gray('\n📦 Containers vinculados:'));
|
|
226
|
+
db.containers.forEach(c => {
|
|
227
|
+
console.log(chalk.white(` • ${c.name} ${chalk.gray(`(${c.id})`)}`));
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
console.log(chalk.gray(`\n📅 Criado em: ${new Date(db.created_at).toLocaleString('pt-BR')}`));
|
|
232
|
+
console.log(chalk.gray(` Atualizado em: ${new Date(db.updated_at).toLocaleString('pt-BR')}`));
|
|
233
|
+
|
|
234
|
+
console.log(chalk.gray('\n🔗 Connection String:'));
|
|
235
|
+
console.log(chalk.cyan(` ${db.connection_string}`));
|
|
236
|
+
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error(chalk.red('\n❌ Erro ao buscar informações:'));
|
|
239
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ============================================
|
|
245
|
+
// CREDENTIALS - Ver credenciais do database
|
|
246
|
+
// ============================================
|
|
247
|
+
async function credentials(identifier) {
|
|
248
|
+
try {
|
|
249
|
+
const spinner = ora('Carregando credenciais...').start();
|
|
250
|
+
const database = await resolveDatabase(identifier);
|
|
251
|
+
|
|
252
|
+
const response = await api.getDatabase(database.id);
|
|
253
|
+
spinner.stop();
|
|
254
|
+
|
|
255
|
+
const db = response.database;
|
|
256
|
+
|
|
257
|
+
console.log(chalk.cyan.bold(`\n🔑 Credenciais de ${db.name}\n`));
|
|
258
|
+
console.log(chalk.white(` Host: ${chalk.cyan(db.host)}`));
|
|
259
|
+
console.log(chalk.white(` Porta: ${chalk.cyan(db.port)}`));
|
|
260
|
+
console.log(chalk.white(` Database: ${chalk.cyan(db.database_name)}`));
|
|
261
|
+
console.log(chalk.white(` Username: ${chalk.cyan(db.username)}`));
|
|
262
|
+
console.log(chalk.white(` Password: ${chalk.yellow(db.password)}`));
|
|
263
|
+
|
|
264
|
+
console.log(chalk.gray('\n🔗 Connection String:'));
|
|
265
|
+
console.log(chalk.cyan(` ${db.connection_string}`));
|
|
266
|
+
|
|
267
|
+
console.log(chalk.gray('\n💡 Copie e cole em suas variáveis de ambiente'));
|
|
268
|
+
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.error(chalk.red('\n❌ Erro ao buscar credenciais:'));
|
|
271
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ============================================
|
|
277
|
+
// LINK - Vincular database a container
|
|
278
|
+
// ============================================
|
|
279
|
+
async function link(databaseIdentifier, containerIdentifier) {
|
|
280
|
+
try {
|
|
281
|
+
if (!containerIdentifier) {
|
|
282
|
+
console.error(chalk.red('❌ Container não especificado'));
|
|
283
|
+
console.log(chalk.gray(' Use: mozhost db:link <database> <container>'));
|
|
284
|
+
process.exit(1);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const spinner = ora('Resolvendo database...').start();
|
|
288
|
+
const database = await resolveDatabase(databaseIdentifier);
|
|
289
|
+
|
|
290
|
+
spinner.text = 'Resolvendo container...';
|
|
291
|
+
// Reusar a função de containers (você precisará exportá-la ou criar similar)
|
|
292
|
+
let containerId;
|
|
293
|
+
try {
|
|
294
|
+
const containerResponse = await api.getContainer(containerIdentifier);
|
|
295
|
+
containerId = containerResponse.container.id;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
if (error.response?.status === 404) {
|
|
298
|
+
const listResponse = await api.listContainers();
|
|
299
|
+
const found = listResponse.containers.find(c =>
|
|
300
|
+
c.name === containerIdentifier ||
|
|
301
|
+
c.id === containerIdentifier ||
|
|
302
|
+
c.id.startsWith(containerIdentifier)
|
|
303
|
+
);
|
|
304
|
+
if (!found) {
|
|
305
|
+
throw new Error(`Container "${containerIdentifier}" não encontrado`);
|
|
306
|
+
}
|
|
307
|
+
containerId = found.id;
|
|
308
|
+
} else {
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
spinner.text = 'Vinculando database ao container...';
|
|
314
|
+
await api.linkDatabase(database.id, containerId);
|
|
315
|
+
|
|
316
|
+
spinner.succeed(chalk.green(`✅ Database ${database.name} vinculado com sucesso!`));
|
|
317
|
+
|
|
318
|
+
console.log(chalk.gray('\n💡 O container agora pode acessar este database'));
|
|
319
|
+
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error(chalk.red('\n❌ Erro ao vincular database:'));
|
|
322
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ============================================
|
|
328
|
+
// DELETE - Deletar database
|
|
329
|
+
// ============================================
|
|
330
|
+
async function deleteDatabase(identifier) {
|
|
331
|
+
try {
|
|
332
|
+
const spinner = ora('Resolvendo database...').start();
|
|
333
|
+
const database = await resolveDatabase(identifier);
|
|
334
|
+
spinner.stop();
|
|
335
|
+
|
|
336
|
+
console.log(chalk.yellow('\n⚠️ ATENÇÃO: Esta ação é irreversível!'));
|
|
337
|
+
console.log(chalk.gray(' Todos os dados serão perdidos permanentemente.\n'));
|
|
338
|
+
|
|
339
|
+
const confirm = await inquirer.prompt([
|
|
340
|
+
{
|
|
341
|
+
type: 'confirm',
|
|
342
|
+
name: 'confirmed',
|
|
343
|
+
message: chalk.red(`Tem certeza que deseja deletar "${database.name}"?`),
|
|
344
|
+
default: false
|
|
345
|
+
}
|
|
346
|
+
]);
|
|
347
|
+
|
|
348
|
+
if (!confirm.confirmed) {
|
|
349
|
+
console.log(chalk.yellow('Operação cancelada'));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Confirmação dupla para databases
|
|
354
|
+
const doubleConfirm = await inquirer.prompt([
|
|
355
|
+
{
|
|
356
|
+
type: 'input',
|
|
357
|
+
name: 'typed',
|
|
358
|
+
message: chalk.red(`Digite o nome do database "${database.name}" para confirmar:`),
|
|
359
|
+
}
|
|
360
|
+
]);
|
|
361
|
+
|
|
362
|
+
if (doubleConfirm.typed !== database.name) {
|
|
363
|
+
console.log(chalk.red('❌ Nome incorreto. Operação cancelada.'));
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const deleteSpinner = ora(`Deletando ${database.name}...`).start();
|
|
368
|
+
await api.deleteDatabase(database.id);
|
|
369
|
+
|
|
370
|
+
deleteSpinner.succeed(chalk.green(`✅ Database ${database.name} deletado com sucesso!`));
|
|
371
|
+
|
|
372
|
+
} catch (error) {
|
|
373
|
+
console.error(chalk.red('\n❌ Erro ao deletar database:'));
|
|
374
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ============================================
|
|
380
|
+
// EXPORTS
|
|
381
|
+
// ============================================
|
|
382
|
+
module.exports = {
|
|
383
|
+
list,
|
|
384
|
+
create,
|
|
385
|
+
info,
|
|
386
|
+
credentials,
|
|
387
|
+
link,
|
|
388
|
+
deleteDatabase
|
|
389
|
+
};
|
package/src/utils/api.js
CHANGED
|
@@ -170,4 +170,37 @@ class ApiClient {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
// Databases
|
|
174
|
+
async listDatabases() {
|
|
175
|
+
const client = await this.getClient();
|
|
176
|
+
const response = await client.get('/api/databases');
|
|
177
|
+
return response.data;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async getDatabase(databaseId) {
|
|
181
|
+
const client = await this.getClient();
|
|
182
|
+
const response = await client.get(`/api/databases/${databaseId}`);
|
|
183
|
+
return response.data;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async createDatabase(data) {
|
|
187
|
+
const client = await this.getClient();
|
|
188
|
+
const response = await client.post('/api/databases', data);
|
|
189
|
+
return response.data;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async deleteDatabase(databaseId) {
|
|
193
|
+
const client = await this.getClient();
|
|
194
|
+
const response = await client.delete(`/api/databases/${databaseId}`);
|
|
195
|
+
return response.data;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async linkDatabase(databaseId, containerId) {
|
|
199
|
+
const client = await this.getClient();
|
|
200
|
+
const response = await client.post(`/api/databases/${databaseId}/link`, {
|
|
201
|
+
container_id: containerId
|
|
202
|
+
});
|
|
203
|
+
return response.data;
|
|
204
|
+
}
|
|
205
|
+
|
|
173
206
|
module.exports = new ApiClient();
|