herdux-cli 0.1.1

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.
Files changed (75) hide show
  1. package/README.md +370 -0
  2. package/README.pt-BR.md +369 -0
  3. package/dist/commands/backup.d.ts +3 -0
  4. package/dist/commands/backup.d.ts.map +1 -0
  5. package/dist/commands/backup.js +66 -0
  6. package/dist/commands/backup.js.map +1 -0
  7. package/dist/commands/clean.d.ts +3 -0
  8. package/dist/commands/clean.d.ts.map +1 -0
  9. package/dist/commands/clean.js +102 -0
  10. package/dist/commands/clean.js.map +1 -0
  11. package/dist/commands/config.d.ts +3 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +146 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/create.d.ts +3 -0
  16. package/dist/commands/create.d.ts.map +1 -0
  17. package/dist/commands/create.js +26 -0
  18. package/dist/commands/create.js.map +1 -0
  19. package/dist/commands/doctor.d.ts +3 -0
  20. package/dist/commands/doctor.d.ts.map +1 -0
  21. package/dist/commands/doctor.js +92 -0
  22. package/dist/commands/doctor.js.map +1 -0
  23. package/dist/commands/drop.d.ts +3 -0
  24. package/dist/commands/drop.d.ts.map +1 -0
  25. package/dist/commands/drop.js +40 -0
  26. package/dist/commands/drop.js.map +1 -0
  27. package/dist/commands/list.d.ts +3 -0
  28. package/dist/commands/list.d.ts.map +1 -0
  29. package/dist/commands/list.js +55 -0
  30. package/dist/commands/list.js.map +1 -0
  31. package/dist/commands/restore.d.ts +3 -0
  32. package/dist/commands/restore.d.ts.map +1 -0
  33. package/dist/commands/restore.js +54 -0
  34. package/dist/commands/restore.js.map +1 -0
  35. package/dist/commands/version.d.ts +3 -0
  36. package/dist/commands/version.d.ts.map +1 -0
  37. package/dist/commands/version.js +42 -0
  38. package/dist/commands/version.js.map +1 -0
  39. package/dist/core/command-runner.d.ts +12 -0
  40. package/dist/core/command-runner.d.ts.map +1 -0
  41. package/dist/core/command-runner.js +20 -0
  42. package/dist/core/command-runner.js.map +1 -0
  43. package/dist/core/logger.d.ts +10 -0
  44. package/dist/core/logger.d.ts.map +1 -0
  45. package/dist/core/logger.js +25 -0
  46. package/dist/core/logger.js.map +1 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +33 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/services/backup.service.d.ts +4 -0
  52. package/dist/services/backup.service.d.ts.map +1 -0
  53. package/dist/services/backup.service.js +99 -0
  54. package/dist/services/backup.service.js.map +1 -0
  55. package/dist/services/config.service.d.ts +26 -0
  56. package/dist/services/config.service.d.ts.map +1 -0
  57. package/dist/services/config.service.js +83 -0
  58. package/dist/services/config.service.js.map +1 -0
  59. package/dist/services/environment.service.d.ts +4 -0
  60. package/dist/services/environment.service.d.ts.map +1 -0
  61. package/dist/services/environment.service.js +51 -0
  62. package/dist/services/environment.service.js.map +1 -0
  63. package/dist/services/postgres.service.d.ts +27 -0
  64. package/dist/services/postgres.service.d.ts.map +1 -0
  65. package/dist/services/postgres.service.js +180 -0
  66. package/dist/services/postgres.service.js.map +1 -0
  67. package/dist/utils/detect-binary.d.ts +3 -0
  68. package/dist/utils/detect-binary.d.ts.map +1 -0
  69. package/dist/utils/detect-binary.js +16 -0
  70. package/dist/utils/detect-binary.js.map +1 -0
  71. package/dist/utils/resolve-connection.d.ts +3 -0
  72. package/dist/utils/resolve-connection.d.ts.map +1 -0
  73. package/dist/utils/resolve-connection.js +107 -0
  74. package/dist/utils/resolve-connection.js.map +1 -0
  75. package/package.json +46 -0
@@ -0,0 +1,369 @@
1
+ 🇧🇷 Português | 🇺🇸 [English](./README.md)
2
+
3
+ # Herdux — Database Workflow CLI
4
+
5
+ <p align="center">
6
+ <strong>Infrastructure-grade power. Developer-grade experience.</strong>
7
+ </p>
8
+
9
+ Uma CLI rápida e interativa que remove a fricção dos workflows diários com bancos de dados locais, especialmente ao lidar com múltiplas instâncias e grandes datasets.
10
+
11
+ ![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)
12
+ ![License](https://img.shields.io/badge/license-MIT-green.svg)
13
+ ![Node](https://img.shields.io/badge/node-18%2B-43853d.svg)
14
+
15
+ > Otimizado para ambientes locais e de desenvolvimento. O uso em produção é suportado com configuração explícita.
16
+
17
+ <p align="center">
18
+ <img src=".github/herdux.gif" alt="herdux terminal gif" width="1220" />
19
+ </p>
20
+
21
+ ---
22
+
23
+ ## ⚡ Início Rápido
24
+
25
+ ```bash
26
+ npm install -g herdux-cli
27
+ herdux doctor
28
+ herdux list
29
+ ```
30
+
31
+ É só isso. Você já está gerenciando bancos de dados.
32
+
33
+ ---
34
+
35
+ ## Por que Herdux?
36
+
37
+ Gerenciar bancos de dados locais através de scripts bash ou binários crus é repetitivo, propenso a erros e doloroso em escala.
38
+
39
+ ### ❌ Sem Herdux
40
+
41
+ ```bash
42
+ # Fazer backup de um banco
43
+ pg_dump -U postgres -h localhost -p 5416 -Fc -f ./backups/mydb_2026-02-23.dump mydb
44
+
45
+ # Depois dropar manualmente
46
+ psql -U postgres -h localhost -p 5416 -c "DROP DATABASE mydb;"
47
+
48
+ # Restaurar do backup
49
+ pg_restore -U postgres -h localhost -p 5416 -d mydb --clean --if-exists ./backups/mydb_2026-02-23.dump
50
+
51
+ # Verificar se as ferramentas estão instaladas
52
+ psql --version && pg_dump --version && pg_restore --version
53
+ ```
54
+
55
+ ### ✅ Com Herdux
56
+
57
+ ```bash
58
+ herdux backup mydb --drop --yes # Backup + drop em um comando
59
+ herdux restore ./backups/mydb.dump --db mydb # Cria o banco (se faltar) e detecta o formato
60
+ herdux clean # Multi-seleção e batch-drop de bancos
61
+ herdux doctor # Verificação completa do sistema
62
+ ```
63
+
64
+ Menos flags. Menos erros. Zero fadiga de terminal.
65
+
66
+ ---
67
+
68
+ ## 🎯 Para quem é o Herdux?
69
+
70
+ O **Herdux** foi construído *por desenvolvedores, para desenvolvedores*.
71
+
72
+ Ele nasceu da frustração diária de ter que constantemente restaurar backups para testar um estado específico, dropar bancos corrompidos durante o desenvolvimento e lidar com binários crus de bancos de dados toda hora.
73
+
74
+ Ele é especificamente projetado para desenvolvedores que:
75
+ - Gerenciam infraestruturas locais e precisam verificar o tamanho dos discos antes de popular novos bancos.
76
+ - Querem clonar, popular (seed) e resetar bancos de dados rapidamente sem precisar ler documentações complexas.
77
+ - Precisam de fluxos seguros de backup & restore que não dependam de scripts bash frágeis.
78
+ - Preferem ferramentas focadas no terminal (terminal-first).
79
+ - Querem resolução previsível de conexões sem mágicas ocultas.
80
+
81
+ Se você gerencia bancos de dados localmente e compartilha dessa dor, o Herdux foi criado para você.
82
+
83
+ ---
84
+
85
+ ## 🚀 Funcionalidades Principais
86
+
87
+ - **📋 Listagem Inteligente** — Estratégia otimizada para clusters massivos. Flag opcional `--size` para análise de uso de disco, ordenado do maior para o menor.
88
+ - **💾 Backup & Restore Inteligente** — Suporta formatos Custom (`.dump`) e Plain (`.sql`). Detecta automaticamente a ferramenta correta para restauração.
89
+ - **🧹 Limpeza em Massa** — Multi-seleção de bancos, backup opcional e batch-drop. Recupere espaço em disco instantaneamente.
90
+ - **🩺 Diagnóstico do Sistema** — Verificação completa de saúde com um único comando: binários, autenticação e conectividade.
91
+ - **⚙️ Perfis Persistentes** — Salve configurações de servidor nomeadas. Alterne entre ambientes com `-s pg16`.
92
+ - **🎯 Resolução Inteligente de Conexão** — Flags CLI explícitas → perfis → padrões salvos → auto-descoberta. Sempre previsível.
93
+
94
+ ---
95
+
96
+ ## 💡 Filosofia
97
+
98
+ **Herdux** combina *herd* (manada/rebanho) e *UX* — entregando uma melhor Developer Experience ao gerenciar seus clusters de bancos de dados. O nome reflete nosso foco em melhorar a experiência de desenvolvimento ao gerenciar "manadas" de bancos.
99
+
100
+ O **Herdux** segue três princípios:
101
+
102
+ - **Segurança primeiro** — Nunca apaga dados sem confirmação explícita ou um backup verificado.
103
+ - **Explícito sobre implícito** — A resolução de conexão segue uma prioridade estrita e documentada. Sem mágica.
104
+ - **Otimização de workflow** — Cada comando é projetado para te salvar de tarefas repetitivas no terminal.
105
+
106
+ ---
107
+
108
+ ## 🔒 Segurança
109
+
110
+ O **Herdux** trata operações destrutivas com cuidado:
111
+
112
+ - **Nunca dropa um banco** sem confirmação explícita
113
+ - **Aborta toda a operação** se um backup de segurança falhar durante o `herdux clean`
114
+ - **Valida códigos de saída do `pg_dump`** antes de considerar um backup bem-sucedido
115
+ - **Requer a flag `--drop`** intencionalmente — dropar nunca é o padrão
116
+ - **`--yes` deve ser combinado com `--drop`** — não é possível pular confirmação sozinho
117
+
118
+ > Se você solicitar um backup antes de dropar e esse backup falhar, o **Herdux** para imediatamente. Nenhum dado é perdido.
119
+
120
+ ---
121
+
122
+ ## 🧩 Requisitos
123
+
124
+ - **Node.js** 18 ou superior
125
+ - **Ferramentas cliente PostgreSQL** (`psql`, `pg_dump`, `pg_restore`) instaladas e disponíveis no `PATH`
126
+
127
+ > [!TIP]
128
+ > Execute `herdux doctor` após a instalação para verificar se tudo está configurado corretamente.
129
+
130
+ ---
131
+
132
+ ## 📦 Instalação
133
+
134
+ **npm (recomendado):**
135
+
136
+ ```bash
137
+ npm install -g herdux-cli
138
+ ```
139
+
140
+ **Pelo código-fonte:**
141
+
142
+ ```bash
143
+ git clone https://github.com/herdux/herdux.git
144
+ cd herdux
145
+ npm install
146
+ npm run build
147
+ npm link
148
+ ```
149
+
150
+ ---
151
+
152
+ ## 🛠️ Comandos
153
+
154
+ ### `herdux version`
155
+
156
+ Mostra a versão da CLI e a versão do servidor PostgreSQL conectado.
157
+
158
+ ```bash
159
+ herdux version
160
+ ```
161
+
162
+ ### `herdux doctor`
163
+
164
+ Executa uma verificação completa de saúde do sistema:
165
+
166
+ - Verifica se `psql`, `pg_dump` e `pg_restore` estão instalados e acessíveis
167
+ - Tenta uma conexão real usando a configuração resolvida
168
+ - Testa autenticação contra o servidor alvo
169
+
170
+ ```bash
171
+ herdux doctor
172
+ ```
173
+
174
+ ---
175
+
176
+ ### 📋 `herdux list`
177
+
178
+ Lista todos os bancos de dados no servidor conectado.
179
+
180
+ ```bash
181
+ herdux list # Listagem rápida (nome, owner, encoding)
182
+ herdux ls --size # Inclui tamanho em disco, ordenado do maior → menor
183
+ ```
184
+
185
+ > [!NOTE]
186
+ > A flag `--size` calcula o uso físico de disco via `pg_database_size()`. Em servidores com dezenas de bancos multi-GB, isso pode levar alguns minutos dependendo da velocidade do disco.
187
+
188
+ ---
189
+
190
+ ### `herdux create <nome>`
191
+
192
+ Cria um novo banco de dados.
193
+
194
+ ```bash
195
+ herdux create meu_novo_db
196
+ ```
197
+
198
+ ### `herdux drop <nome>`
199
+
200
+ Remove um banco de dados com confirmação interativa.
201
+
202
+ ```bash
203
+ herdux drop meu_banco_antigo
204
+ ```
205
+
206
+ ---
207
+
208
+ ### 🧹 `herdux clean` — Limpeza em Massa
209
+
210
+ Trabalhando com bancos de desenvolvimento cheios de seeds? Precisa recuperar espaço em disco rápido?
211
+
212
+ `herdux clean` permite:
213
+
214
+ - **Multi-seleção** de bancos a partir de uma interface interativa com checkboxes
215
+ - **Gerar backups de segurança opcionais** antes de qualquer ação destrutiva
216
+ - **Batch-drop** de todos os bancos selecionados com segurança
217
+ - **Abortar imediatamente** se qualquer backup falhar, prevenindo perda de dados
218
+
219
+ ```bash
220
+ herdux clean
221
+ ```
222
+
223
+ Projetado para o workflow real do desenvolvedor: clonar bancos, experimentar, depois limpar tudo de uma vez.
224
+
225
+ ---
226
+
227
+ ### 📦 `herdux backup <banco>`
228
+
229
+ Gera um backup com timestamp em `./backups/`.
230
+
231
+ ```bash
232
+ herdux backup mydb # Formato custom (.dump)
233
+ herdux backup mydb --format plain # SQL puro (.sql)
234
+ herdux backup mydb --drop # Backup, depois pergunta se quer dropar
235
+ herdux backup mydb --drop --yes # Backup + drop, sem perguntas
236
+ herdux backup mydb -o ./meus-backups # Diretório de saída personalizado
237
+ ```
238
+
239
+ | Opção | Descrição |
240
+ |---|---|
241
+ | `-F, --format <tipo>` | `custom` (padrão, comprimido) ou `plain` (SQL puro) |
242
+ | `-d, --drop` | Pergunta se deseja dropar o banco após backup bem-sucedido |
243
+ | `-y, --yes` | Pula confirmação do drop (requer `--drop`) |
244
+ | `-o, --output <dir>` | Diretório de saída (padrão: `./backups`) |
245
+
246
+ ---
247
+
248
+ ### 📥 `herdux restore <arquivo>`
249
+
250
+ Restaura um banco de dados a partir de um arquivo de backup. Detecta automaticamente o formato:
251
+
252
+ - `.sql` → usa `psql -f`
253
+ - `.dump` ou qualquer outra extensão → usa `pg_restore`
254
+
255
+ ```bash
256
+ herdux restore ./backups/mydb_2026-02-23.dump --db mydb
257
+ herdux restore ./exports/data.sql --db mydb
258
+ ```
259
+
260
+ Precisa sobrescrever a auto-detecção? Use `--format`:
261
+
262
+ ```bash
263
+ herdux restore arquivo.bkp --db mydb --format custom
264
+ herdux restore script.txt --db mydb --format plain
265
+ ```
266
+
267
+ ---
268
+
269
+ ## ⚙️ Configuração & Perfis de Servidor
270
+
271
+ O `herdux` armazena configurações localmente em `~/.herdux/config.json`.
272
+
273
+ ### Definir Padrões Globais
274
+
275
+ ```bash
276
+ herdux config set user postgres
277
+ herdux config set password minha_senha
278
+ herdux config set port 5432
279
+ ```
280
+
281
+ ### Perfis de Servidor Nomeados
282
+
283
+ Gerencie múltiplas instâncias de banco de dados sem esforço:
284
+
285
+ ```bash
286
+ herdux config add pg16 --port 5416
287
+ herdux config add pg17 --port 5417 --user admin
288
+ herdux config add staging --host 192.168.0.10 --port 5432
289
+ ```
290
+
291
+ Depois conecte usando a flag `-s`:
292
+
293
+ ```bash
294
+ herdux list -s pg16
295
+ herdux backup mydb -s staging
296
+ ```
297
+
298
+ ### Visualizar & Gerenciar Config
299
+
300
+ ```bash
301
+ herdux config list # Mostra todas as configurações e perfis salvos
302
+ herdux config get port # Obtém um valor específico
303
+ herdux config rm pg16 # Remove um perfil de servidor
304
+ herdux config reset # Limpa toda a configuração
305
+ ```
306
+
307
+ ---
308
+
309
+ ## 🔌 Prioridade de Conexão
310
+
311
+ Ao resolver como se conectar, o **Herdux** segue uma ordem de prioridade estrita e previsível:
312
+
313
+ | Prioridade | Fonte | Exemplo |
314
+ |---|---|---|
315
+ | 1️⃣ | **Flags CLI** | `herdux list --port 5417` |
316
+ | 2️⃣ | **Perfil de servidor** | `herdux list -s pg16` |
317
+ | 3️⃣ | **Padrões salvos** | `herdux config set port 5432` |
318
+ | 4️⃣ | **Auto-descoberta** | Escaneia portas comuns; pergunta se encontrar múltiplas |
319
+
320
+ Isso significa que a entrada explícita sempre vence. Sem surpresas.
321
+
322
+ ---
323
+
324
+ ## 🤔 Por que não pgAdmin?
325
+
326
+ O **Herdux** não é um substituto de GUI.
327
+ É um acelerador de workflow para desenvolvedores que vivem no terminal.
328
+
329
+ Sem GUI. Sem overhead. Só velocidade.
330
+
331
+ ---
332
+
333
+ ## 🧠 Princípios de Design
334
+
335
+ - Sem padrões ocultos (hidden defaults).
336
+ - Sem mágicas destrutivas.
337
+ - Resolução de conexão determinística.
338
+ - Comandos explícitos e combináveis.
339
+
340
+ ---
341
+
342
+ ## 🐳 Suporte Docker (Em Breve)
343
+
344
+ O **Herdux** poderá detectar e interagir com instâncias PostgreSQL rodando dentro de containers Docker — listando, conectando e gerenciando-as tão naturalmente quanto instâncias locais.
345
+
346
+ ---
347
+
348
+ ## 🗺 Roadmap
349
+
350
+ Consulte o [ROADMAP.md](./ROADMAP.md) para ver nossos planos futuros detalhados, incluindo integração com Docker e backups criptografados.
351
+
352
+ ---
353
+
354
+ ## 🤝 Contribuindo
355
+
356
+ PRs são bem-vindas! Por favor, abra uma issue primeiro para discutir mudanças significativas.
357
+
358
+ ```bash
359
+ git clone https://github.com/herdux/herdux.git
360
+ cd herdux
361
+ npm install
362
+ npm run dev
363
+ ```
364
+
365
+ ---
366
+
367
+ ## 📄 Licença
368
+
369
+ MIT
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerBackupCommand(program: Command): void;
3
+ //# sourceMappingURL=backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgG5D"}
@@ -0,0 +1,66 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import prompts from "prompts";
4
+ import { checkPostgresClient, checkPgDump, } from "../services/environment.service.js";
5
+ import * as backup from "../services/backup.service.js";
6
+ import * as postgres from "../services/postgres.service.js";
7
+ import * as config from "../services/config.service.js";
8
+ import { resolveConnectionOptions } from "../utils/resolve-connection.js";
9
+ import { join } from "path";
10
+ import { homedir } from "os";
11
+ export function registerBackupCommand(program) {
12
+ program
13
+ .command("backup <database>")
14
+ .description("Create a backup of a database")
15
+ .option("-o, --output <dir>", "Output directory for the backup (overrides global config)")
16
+ .option("-d, --drop", "Ask to drop the database after a successful backup")
17
+ .option("-y, --yes", "Skip confirmation when dropping (requires --drop)")
18
+ .option("-F, --format <type>", "Backup format format (custom, plain)", "custom")
19
+ .action(async (database, cmdOpts) => {
20
+ try {
21
+ await checkPostgresClient();
22
+ await checkPgDump();
23
+ const rawOpts = program.opts();
24
+ const opts = await resolveConnectionOptions(rawOpts, rawOpts.server);
25
+ if (cmdOpts.format !== "custom" && cmdOpts.format !== "plain") {
26
+ console.error(chalk.red(`\n✖ Invalid format "${cmdOpts.format}". Use "custom" or "plain".\n`));
27
+ process.exit(1);
28
+ }
29
+ const configDefaults = config.getDefault();
30
+ let finalOutputDir = cmdOpts.output;
31
+ if (!finalOutputDir) {
32
+ finalOutputDir =
33
+ configDefaults.output || join(homedir(), ".herdux", "backups");
34
+ }
35
+ const spinner = ora(`Generating backup for "${database}"...`).start();
36
+ const outputPath = await backup.backupDatabase(database, finalOutputDir, opts, cmdOpts.format);
37
+ spinner.succeed(`Backup saved at ${chalk.cyan(outputPath)}\n`);
38
+ if (cmdOpts.drop) {
39
+ let shouldDrop = cmdOpts.yes;
40
+ if (!shouldDrop) {
41
+ const response = await prompts({
42
+ type: "confirm",
43
+ name: "confirmDrop",
44
+ message: `Are you sure you want to drop the database "${database}"?`,
45
+ initial: false,
46
+ });
47
+ shouldDrop = response.confirmDrop;
48
+ }
49
+ if (shouldDrop) {
50
+ const dropSpinner = ora(`Dropping database "${database}"...`).start();
51
+ await postgres.dropDatabase(database, opts);
52
+ dropSpinner.succeed(`Database "${database}" dropped successfully\n`);
53
+ }
54
+ else {
55
+ console.log(chalk.gray(` Skipped dropping database "${database}".\n`));
56
+ }
57
+ }
58
+ }
59
+ catch (err) {
60
+ const message = err instanceof Error ? err.message : String(err);
61
+ console.error(chalk.red(`\n✖ ${message}\n`));
62
+ process.exit(1);
63
+ }
64
+ });
65
+ }
66
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerCleanCommand(program: Command): void;
3
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2H3D"}
@@ -0,0 +1,102 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import prompts from "prompts";
4
+ import { checkPostgresClient, checkPgDump, } from "../services/environment.service.js";
5
+ import * as postgres from "../services/postgres.service.js";
6
+ import * as backup from "../services/backup.service.js";
7
+ import * as config from "../services/config.service.js";
8
+ import { resolveConnectionOptions } from "../utils/resolve-connection.js";
9
+ import { join } from "path";
10
+ import { homedir } from "os";
11
+ export function registerCleanCommand(program) {
12
+ program
13
+ .command("clean")
14
+ .description("Interactive bulk cleanup tool to drop multiple databases")
15
+ .action(async () => {
16
+ try {
17
+ await checkPostgresClient();
18
+ const rawOpts = program.opts();
19
+ const opts = await resolveConnectionOptions(rawOpts, rawOpts.server);
20
+ let spinner = ora("Fetching databases...").start();
21
+ const databases = await postgres.listDatabases(opts);
22
+ spinner.stop();
23
+ if (databases.length === 0) {
24
+ console.log(chalk.yellow(" No databases found to clean.\n"));
25
+ return;
26
+ }
27
+ const response = await prompts({
28
+ type: "multiselect",
29
+ name: "selectedDbs",
30
+ message: "Select databases to DROP (Space to select, Enter to confirm):",
31
+ choices: databases.map((db) => ({
32
+ title: `${db.name} (owner: ${db.owner})`,
33
+ value: db.name,
34
+ })),
35
+ min: 1,
36
+ hint: "- Space to select. Return to submit",
37
+ });
38
+ const selectedDbs = response.selectedDbs;
39
+ if (!selectedDbs || selectedDbs.length === 0) {
40
+ console.log(chalk.yellow("\n⚠ Clean operation cancelled.\n"));
41
+ return;
42
+ }
43
+ console.log(chalk.red(`\nYou selected ${selectedDbs.length} database(s) for deletion.`));
44
+ const backupResponse = await prompts({
45
+ type: "confirm",
46
+ name: "backupFirst",
47
+ message: "Would you like to backup these databases before dropping them?",
48
+ initial: true,
49
+ });
50
+ if (backupResponse.backupFirst) {
51
+ await checkPgDump();
52
+ const configDefaults = config.getDefault();
53
+ const backupDir = configDefaults.output || join(homedir(), ".herdux", "backups");
54
+ console.log(chalk.cyan("\nStarting backups..."));
55
+ for (const db of selectedDbs) {
56
+ spinner = ora(`Backing up "${db}"...`).start();
57
+ try {
58
+ const outObj = await backup.backupDatabase(db, backupDir, opts, "custom");
59
+ spinner.succeed(`Saved to ${outObj}`);
60
+ }
61
+ catch (err) {
62
+ spinner.fail(`Failed to backup ${db}`);
63
+ const message = err instanceof Error ? err.message : String(err);
64
+ console.error(chalk.red(` ↳ ${message}`));
65
+ console.log(chalk.yellow("\n⚠ Aborting clean process to prevent data loss without backup."));
66
+ process.exit(1);
67
+ }
68
+ }
69
+ }
70
+ const confirmDelete = await prompts({
71
+ type: "confirm",
72
+ name: "confirm",
73
+ message: chalk.red(`Are you absolutely sure you want to DROP ${selectedDbs.length} database(s)? This action is irreversible.`),
74
+ initial: false,
75
+ });
76
+ if (!confirmDelete.confirm) {
77
+ console.log(chalk.yellow("\n⚠ Clean operation aborted.\n"));
78
+ return;
79
+ }
80
+ console.log();
81
+ for (const db of selectedDbs) {
82
+ spinner = ora(`Dropping "${db}"...`).start();
83
+ try {
84
+ await postgres.dropDatabase(db, opts);
85
+ spinner.succeed(`Dropped "${db}"`);
86
+ }
87
+ catch (err) {
88
+ spinner.fail(`Failed to drop "${db}"`);
89
+ const message = err instanceof Error ? err.message : String(err);
90
+ console.error(chalk.red(` ↳ ${message}`));
91
+ }
92
+ }
93
+ console.log(chalk.green(`\n✔ Clean operation completed!`));
94
+ }
95
+ catch (err) {
96
+ const message = err instanceof Error ? err.message : String(err);
97
+ console.error(chalk.red(`\n✖ ${message}\n`));
98
+ process.exit(1);
99
+ }
100
+ });
101
+ }
102
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerConfigCommand(program: Command): void;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuK5D"}