mozhost-cli 2.0.0 β 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/containers.js +158 -70
- package/src/commands/databases.js +389 -0
- package/src/commands/domain.js +78 -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
|
@@ -3,12 +3,60 @@ const ora = require('ora');
|
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
4
|
const api = require('../utils/api');
|
|
5
5
|
|
|
6
|
+
// ============================================
|
|
7
|
+
// HELPER FUNCTION - Resolver Nome ou ID
|
|
8
|
+
// ============================================
|
|
9
|
+
async function resolveContainer(identifier) {
|
|
10
|
+
try {
|
|
11
|
+
// Tenta buscar diretamente por ID
|
|
12
|
+
const response = await api.getContainer(identifier);
|
|
13
|
+
return response.container;
|
|
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.listContainers();
|
|
18
|
+
|
|
19
|
+
// Procura por nome, ID completo ou ID parcial
|
|
20
|
+
const found = listResponse.containers.find(c =>
|
|
21
|
+
c.name === identifier ||
|
|
22
|
+
c.id === identifier ||
|
|
23
|
+
c.id.startsWith(identifier)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (!found) {
|
|
27
|
+
// Procura containers similares para sugerir
|
|
28
|
+
const similar = listResponse.containers.filter(c =>
|
|
29
|
+
c.name.toLowerCase().includes(identifier.toLowerCase()) ||
|
|
30
|
+
c.id.includes(identifier)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (similar.length > 0) {
|
|
34
|
+
console.log(chalk.yellow('\nπ‘ VocΓͺ quis dizer:'));
|
|
35
|
+
similar.forEach(c => {
|
|
36
|
+
console.log(chalk.white(` β’ ${c.name} ${chalk.gray(`(${c.id.slice(0, 8)})`)}`));
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
console.log(chalk.gray('\nπ‘ Use: mozhost ls para ver todos os containers'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new Error(`Container "${identifier}" nΓ£o encontrado`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return found;
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ============================================
|
|
52
|
+
// LIST - Listar todos os containers
|
|
53
|
+
// ============================================
|
|
6
54
|
async function list() {
|
|
7
55
|
try {
|
|
8
56
|
const spinner = ora('Carregando containers...').start();
|
|
9
|
-
|
|
57
|
+
|
|
10
58
|
const response = await api.listContainers();
|
|
11
|
-
|
|
59
|
+
|
|
12
60
|
spinner.stop();
|
|
13
61
|
|
|
14
62
|
if (response.containers.length === 0) {
|
|
@@ -22,7 +70,7 @@ async function list() {
|
|
|
22
70
|
response.containers.forEach(container => {
|
|
23
71
|
const statusColor = container.status === 'running' ? chalk.green : chalk.gray;
|
|
24
72
|
const statusIcon = container.status === 'running' ? 'β' : 'β';
|
|
25
|
-
|
|
73
|
+
|
|
26
74
|
console.log(`${statusColor(statusIcon)} ${chalk.white.bold(container.name)} ${chalk.gray(`(${container.id.slice(0, 8)})`)}`);
|
|
27
75
|
console.log(` ${chalk.gray('Tipo:')} ${container.type}`);
|
|
28
76
|
console.log(` ${chalk.gray('Status:')} ${statusColor(container.status)}`);
|
|
@@ -51,6 +99,9 @@ async function list() {
|
|
|
51
99
|
}
|
|
52
100
|
}
|
|
53
101
|
|
|
102
|
+
// ============================================
|
|
103
|
+
// CREATE - Criar novo container
|
|
104
|
+
// ============================================
|
|
54
105
|
async function create(options) {
|
|
55
106
|
try {
|
|
56
107
|
const { name, type } = options;
|
|
@@ -79,85 +130,106 @@ async function create(options) {
|
|
|
79
130
|
console.log(chalk.white(` Porta: ${response.container.port}`));
|
|
80
131
|
|
|
81
132
|
console.log(chalk.gray('\nPrΓ³ximos passos:'));
|
|
82
|
-
console.log(chalk.white(` 1. mozhost start ${response.container.
|
|
83
|
-
console.log(chalk.white(` 2. mozhost deploy ${response.container.
|
|
133
|
+
console.log(chalk.white(` 1. mozhost start ${response.container.name}`));
|
|
134
|
+
console.log(chalk.white(` 2. mozhost deploy ${response.container.name}`));
|
|
84
135
|
|
|
85
136
|
} catch (error) {
|
|
86
137
|
console.error(chalk.red('\nβ Erro ao criar container:'));
|
|
87
|
-
|
|
138
|
+
|
|
88
139
|
if (error.response?.data) {
|
|
89
140
|
console.error(chalk.red(` ${error.response.data.error || error.response.data.message}`));
|
|
90
|
-
|
|
141
|
+
|
|
91
142
|
if (error.response.status === 403) {
|
|
92
143
|
console.log(chalk.yellow('\nπ‘ Dica: VocΓͺ atingiu o limite de containers do seu plano'));
|
|
93
144
|
}
|
|
94
|
-
|
|
145
|
+
|
|
95
146
|
if (error.response.status === 402) {
|
|
96
147
|
console.log(chalk.yellow('\nπ‘ Dica: VocΓͺ nΓ£o tem coins suficientes'));
|
|
97
148
|
}
|
|
98
149
|
} else {
|
|
99
150
|
console.error(chalk.red(` ${error.message}`));
|
|
100
151
|
}
|
|
101
|
-
|
|
152
|
+
|
|
102
153
|
process.exit(1);
|
|
103
154
|
}
|
|
104
155
|
}
|
|
105
156
|
|
|
106
|
-
|
|
157
|
+
// ============================================
|
|
158
|
+
// START - Iniciar container
|
|
159
|
+
// ============================================
|
|
160
|
+
async function start(identifier) {
|
|
107
161
|
try {
|
|
108
|
-
const spinner = ora('
|
|
109
|
-
|
|
110
|
-
const response = await api.startContainer(containerId);
|
|
162
|
+
const spinner = ora('Resolvendo container...').start();
|
|
163
|
+
const container = await resolveContainer(identifier);
|
|
111
164
|
|
|
112
|
-
spinner.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
165
|
+
spinner.text = `Iniciando ${container.name}...`;
|
|
166
|
+
const response = await api.startContainer(container.id);
|
|
167
|
+
|
|
168
|
+
spinner.succeed(chalk.green(`β
Container ${container.name} iniciado!`));
|
|
169
|
+
|
|
170
|
+
console.log(chalk.cyan(`\nπ URL: https://${container.domain}`));
|
|
116
171
|
|
|
117
172
|
} catch (error) {
|
|
118
173
|
console.error(chalk.red('\nβ Erro ao iniciar container:'));
|
|
119
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
174
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
120
175
|
process.exit(1);
|
|
121
176
|
}
|
|
122
177
|
}
|
|
123
178
|
|
|
124
|
-
|
|
179
|
+
// ============================================
|
|
180
|
+
// STOP - Parar container
|
|
181
|
+
// ============================================
|
|
182
|
+
async function stop(identifier) {
|
|
125
183
|
try {
|
|
126
|
-
const spinner = ora('
|
|
184
|
+
const spinner = ora('Resolvendo container...').start();
|
|
185
|
+
const container = await resolveContainer(identifier);
|
|
127
186
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
187
|
+
spinner.text = `Parando ${container.name}...`;
|
|
188
|
+
await api.stopContainer(container.id);
|
|
189
|
+
|
|
190
|
+
spinner.succeed(chalk.green(`β
Container ${container.name} parado!`));
|
|
131
191
|
|
|
132
192
|
} catch (error) {
|
|
133
193
|
console.error(chalk.red('\nβ Erro ao parar container:'));
|
|
134
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
194
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
135
195
|
process.exit(1);
|
|
136
196
|
}
|
|
137
197
|
}
|
|
138
198
|
|
|
139
|
-
|
|
199
|
+
// ============================================
|
|
200
|
+
// RESTART - Reiniciar container
|
|
201
|
+
// ============================================
|
|
202
|
+
async function restart(identifier) {
|
|
140
203
|
try {
|
|
141
|
-
const spinner = ora('
|
|
204
|
+
const spinner = ora('Resolvendo container...').start();
|
|
205
|
+
const container = await resolveContainer(identifier);
|
|
142
206
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
207
|
+
spinner.text = `Reiniciando ${container.name}...`;
|
|
208
|
+
await api.restartContainer(container.id);
|
|
209
|
+
|
|
210
|
+
spinner.succeed(chalk.green(`β
Container ${container.name} reiniciado!`));
|
|
146
211
|
|
|
147
212
|
} catch (error) {
|
|
148
213
|
console.error(chalk.red('\nβ Erro ao reiniciar container:'));
|
|
149
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
214
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
150
215
|
process.exit(1);
|
|
151
216
|
}
|
|
152
217
|
}
|
|
153
218
|
|
|
154
|
-
|
|
219
|
+
// ============================================
|
|
220
|
+
// DELETE - Deletar container
|
|
221
|
+
// ============================================
|
|
222
|
+
async function deleteContainer(identifier) {
|
|
155
223
|
try {
|
|
224
|
+
const spinner = ora('Resolvendo container...').start();
|
|
225
|
+
const container = await resolveContainer(identifier);
|
|
226
|
+
spinner.stop();
|
|
227
|
+
|
|
156
228
|
const confirm = await inquirer.prompt([
|
|
157
229
|
{
|
|
158
230
|
type: 'confirm',
|
|
159
231
|
name: 'confirmed',
|
|
160
|
-
message: chalk.red(
|
|
232
|
+
message: chalk.red(`Tem certeza que deseja deletar "${container.name}"?`),
|
|
161
233
|
default: false
|
|
162
234
|
}
|
|
163
235
|
]);
|
|
@@ -167,70 +239,80 @@ async function deleteContainer(containerId) {
|
|
|
167
239
|
return;
|
|
168
240
|
}
|
|
169
241
|
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
spinner.succeed(chalk.green('β
Container deletado com sucesso!'));
|
|
242
|
+
const deleteSpinner = ora(`Deletando ${container.name}...`).start();
|
|
243
|
+
await api.deleteContainer(container.id);
|
|
244
|
+
|
|
245
|
+
deleteSpinner.succeed(chalk.green(`β
Container ${container.name} deletado com sucesso!`));
|
|
175
246
|
|
|
176
247
|
} catch (error) {
|
|
177
248
|
console.error(chalk.red('\nβ Erro ao deletar container:'));
|
|
178
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
249
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
179
250
|
process.exit(1);
|
|
180
251
|
}
|
|
181
252
|
}
|
|
182
253
|
|
|
183
|
-
|
|
254
|
+
// ============================================
|
|
255
|
+
// LOGS - Ver logs do container
|
|
256
|
+
// ============================================
|
|
257
|
+
async function logs(identifier, options) {
|
|
184
258
|
try {
|
|
185
|
-
const spinner = ora('
|
|
186
|
-
|
|
187
|
-
const response = await api.getContainerLogs(containerId, options.lines);
|
|
259
|
+
const spinner = ora('Resolvendo container...').start();
|
|
260
|
+
const container = await resolveContainer(identifier);
|
|
188
261
|
|
|
262
|
+
spinner.text = `Carregando logs de ${container.name}...`;
|
|
263
|
+
const response = await api.getContainerLogs(container.id, options.lines);
|
|
264
|
+
|
|
189
265
|
spinner.stop();
|
|
190
266
|
|
|
191
267
|
if (!response.logs || response.logs.length === 0) {
|
|
192
|
-
console.log(chalk.yellow(
|
|
268
|
+
console.log(chalk.yellow(`\nβ οΈ Nenhum log encontrado para ${container.name}`));
|
|
193
269
|
return;
|
|
194
270
|
}
|
|
195
271
|
|
|
196
|
-
console.log(chalk.cyan.bold(
|
|
272
|
+
console.log(chalk.cyan.bold(`\nπ Logs de ${container.name}\n`));
|
|
197
273
|
response.logs.forEach(line => {
|
|
198
274
|
console.log(chalk.gray(line));
|
|
199
275
|
});
|
|
200
276
|
|
|
201
277
|
} catch (error) {
|
|
202
278
|
console.error(chalk.red('\nβ Erro ao buscar logs:'));
|
|
203
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
279
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
204
280
|
process.exit(1);
|
|
205
281
|
}
|
|
206
282
|
}
|
|
207
283
|
|
|
208
|
-
|
|
284
|
+
// ============================================
|
|
285
|
+
// INFO - InformaΓ§Γ΅es detalhadas do container
|
|
286
|
+
// ============================================
|
|
287
|
+
async function info(identifier) {
|
|
209
288
|
try {
|
|
210
|
-
const spinner = ora('
|
|
289
|
+
const spinner = ora('Resolvendo container...').start();
|
|
290
|
+
const container = await resolveContainer(identifier);
|
|
211
291
|
|
|
212
|
-
|
|
292
|
+
spinner.text = `Carregando informaΓ§Γ΅es de ${container.name}...`;
|
|
213
293
|
|
|
294
|
+
// Busca detalhes completos (com stats se disponΓvel)
|
|
295
|
+
const response = await api.getContainer(container.id);
|
|
214
296
|
spinner.stop();
|
|
215
297
|
|
|
216
|
-
const
|
|
217
|
-
|
|
298
|
+
const containerData = response.container;
|
|
299
|
+
|
|
218
300
|
console.log(chalk.cyan.bold('\nπ¦ InformaΓ§Γ΅es do Container\n'));
|
|
219
|
-
console.log(chalk.white(` ID: ${
|
|
220
|
-
console.log(chalk.white(` Nome: ${
|
|
221
|
-
console.log(chalk.white(` Tipo: ${
|
|
222
|
-
|
|
223
|
-
const statusColor =
|
|
224
|
-
console.log(` Status: ${statusColor(
|
|
225
|
-
|
|
226
|
-
console.log(chalk.cyan(` URL: https://${
|
|
227
|
-
console.log(chalk.white(` Porta: ${
|
|
228
|
-
console.log(chalk.white(` CPU Limit: ${
|
|
229
|
-
console.log(chalk.white(` RAM Limit: ${
|
|
230
|
-
console.log(chalk.white(` Storage Usado: ${
|
|
231
|
-
console.log(chalk.white(` Auto Restart: ${
|
|
232
|
-
console.log(chalk.gray(` Criado em: ${new Date(
|
|
233
|
-
console.log(chalk.gray(` Atualizado em: ${new Date(
|
|
301
|
+
console.log(chalk.white(` ID: ${containerData.id}`));
|
|
302
|
+
console.log(chalk.white(` Nome: ${containerData.name}`));
|
|
303
|
+
console.log(chalk.white(` Tipo: ${containerData.type}`));
|
|
304
|
+
|
|
305
|
+
const statusColor = containerData.status === 'running' ? chalk.green : chalk.gray;
|
|
306
|
+
console.log(` Status: ${statusColor(containerData.status)}`);
|
|
307
|
+
|
|
308
|
+
console.log(chalk.cyan(` URL: https://${containerData.domain}`));
|
|
309
|
+
console.log(chalk.white(` Porta: ${containerData.port}`));
|
|
310
|
+
console.log(chalk.white(` CPU Limit: ${containerData.cpu_limit}`));
|
|
311
|
+
console.log(chalk.white(` RAM Limit: ${containerData.memory_limit_mb}MB`));
|
|
312
|
+
console.log(chalk.white(` Storage Usado: ${containerData.storage_used_mb || 0}MB`));
|
|
313
|
+
console.log(chalk.white(` Auto Restart: ${containerData.auto_restart ? 'Sim' : 'NΓ£o'}`));
|
|
314
|
+
console.log(chalk.gray(` Criado em: ${new Date(containerData.created_at).toLocaleString('pt-BR')}`));
|
|
315
|
+
console.log(chalk.gray(` Atualizado em: ${new Date(containerData.updated_at).toLocaleString('pt-BR')}`));
|
|
234
316
|
|
|
235
317
|
if (response.stats) {
|
|
236
318
|
console.log(chalk.cyan.bold('\nπ EstatΓsticas em Tempo Real\n'));
|
|
@@ -240,22 +322,28 @@ async function info(containerId) {
|
|
|
240
322
|
|
|
241
323
|
} catch (error) {
|
|
242
324
|
console.error(chalk.red('\nβ Erro ao buscar informaΓ§Γ΅es:'));
|
|
243
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
325
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
244
326
|
process.exit(1);
|
|
245
327
|
}
|
|
246
328
|
}
|
|
247
329
|
|
|
248
|
-
|
|
330
|
+
// ============================================
|
|
331
|
+
// URL - Obter URL do container
|
|
332
|
+
// ============================================
|
|
333
|
+
async function url(identifier) {
|
|
249
334
|
try {
|
|
250
|
-
const
|
|
251
|
-
console.log(chalk.cyan(`https://${
|
|
335
|
+
const container = await resolveContainer(identifier);
|
|
336
|
+
console.log(chalk.cyan(`https://${container.domain}`));
|
|
252
337
|
} catch (error) {
|
|
253
338
|
console.error(chalk.red('β Erro ao buscar URL:'));
|
|
254
|
-
console.error(chalk.red(` ${error.response?.data?.error
|
|
339
|
+
console.error(chalk.red(` ${error.message || error.response?.data?.error}`));
|
|
255
340
|
process.exit(1);
|
|
256
341
|
}
|
|
257
342
|
}
|
|
258
343
|
|
|
344
|
+
// ============================================
|
|
345
|
+
// EXPORTS
|
|
346
|
+
// ============================================
|
|
259
347
|
module.exports = {
|
|
260
348
|
list,
|
|
261
349
|
create,
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// mozhost-cli/commands/domain.js
|
|
2
|
+
|
|
3
|
+
const program = require('commander');
|
|
4
|
+
const axios = require('axios');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.command('domain add <container> <domain>')
|
|
9
|
+
.description('Adicionar domΓnio customizado')
|
|
10
|
+
.action(async (container, domain) => {
|
|
11
|
+
try {
|
|
12
|
+
const res = await axios.post(`${API_URL}/domains`, {
|
|
13
|
+
containerId: container,
|
|
14
|
+
domain
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log(chalk.green('\nβ
DomΓnio adicionado com sucesso!\n'));
|
|
18
|
+
console.log(chalk.yellow('π Configure seu DNS:\n'));
|
|
19
|
+
console.log(` Tipo: ${chalk.bold('A')}`);
|
|
20
|
+
console.log(` Nome: ${chalk.bold('@')} (ou ${chalk.bold(domain)})`);
|
|
21
|
+
console.log(` Valor: ${chalk.bold(res.data.instructions.ip)}`);
|
|
22
|
+
console.log(` TTL: ${chalk.bold('300')}\n`);
|
|
23
|
+
console.log(chalk.cyan('β³ Aguardando propagaΓ§Γ£o DNS...\n'));
|
|
24
|
+
console.log(`Use ${chalk.bold('mozhost domain status ' + container)} para acompanhar\n`);
|
|
25
|
+
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(chalk.red('β Erro:'), error.response?.data?.error || error.message);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
program
|
|
32
|
+
.command('domain status <container>')
|
|
33
|
+
.description('Ver status dos domΓnios')
|
|
34
|
+
.action(async (container) => {
|
|
35
|
+
try {
|
|
36
|
+
const res = await axios.get(`${API_URL}/domains/${container}`);
|
|
37
|
+
const domains = res.data;
|
|
38
|
+
|
|
39
|
+
if (domains.length === 0) {
|
|
40
|
+
console.log(chalk.yellow('Nenhum domΓnio customizado configurado'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('\nβββββββββββββββββββββββββββββββββββββββββββββββββββ');
|
|
45
|
+
|
|
46
|
+
for (const d of domains) {
|
|
47
|
+
const statusIcon = {
|
|
48
|
+
pending: 'β³',
|
|
49
|
+
dns_pending: 'π',
|
|
50
|
+
ssl_generating: 'π',
|
|
51
|
+
active: 'β
',
|
|
52
|
+
failed: 'β'
|
|
53
|
+
}[d.status];
|
|
54
|
+
|
|
55
|
+
const statusText = {
|
|
56
|
+
pending: 'Aguardando configuraΓ§Γ£o',
|
|
57
|
+
dns_pending: 'DNS detectado, gerando SSL...',
|
|
58
|
+
ssl_generating: 'Gerando certificado SSL...',
|
|
59
|
+
active: 'Ativo',
|
|
60
|
+
failed: 'Falhou - verifique DNS'
|
|
61
|
+
}[d.status];
|
|
62
|
+
|
|
63
|
+
console.log(`β ${statusIcon} ${chalk.bold(d.domain)}`);
|
|
64
|
+
console.log(`β Status: ${statusText}`);
|
|
65
|
+
if (d.ssl_expires_at && d.status === 'active') {
|
|
66
|
+
console.log(`β SSL vΓ‘lido atΓ©: ${new Date(d.ssl_expires_at).toLocaleDateString()}`);
|
|
67
|
+
}
|
|
68
|
+
console.log('β');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log('βββββββββββββββββββββββββββββββββββββββββββββββββββ\n');
|
|
72
|
+
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error(chalk.red('β Erro:'), error.message);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
program.parse(process.argv);
|
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();
|