smoonb 0.0.59 → 0.0.60
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/README.md +34 -0
- package/bin/smoonb.js +13 -2
- package/package.json +1 -1
- package/src/commands/import.js +91 -0
- package/src/index.js +3 -1
package/README.md
CHANGED
|
@@ -242,6 +242,39 @@ npx smoonb restore
|
|
|
242
242
|
- ✅ `.backup.gz` (compactado) - Descompacta automaticamente antes de restaurar
|
|
243
243
|
- ✅ `.backup` (descompactado) - Restaura diretamente
|
|
244
244
|
|
|
245
|
+
### Importar Backup do Dashboard do Supabase
|
|
246
|
+
|
|
247
|
+
Se você baixou um backup diretamente do Dashboard do Supabase (formato `.backup.gz`), você pode importá-lo para o formato esperado pelo smoonb:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
npx smoonb import --file "caminho/completo/para/db_cluster-04-03-2024@14-16-59.backup.gz"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**O que o comando faz:**
|
|
254
|
+
1. Lê o arquivo `.backup.gz` do Dashboard
|
|
255
|
+
2. Extrai informações do nome do arquivo (data e hora)
|
|
256
|
+
3. Cria uma pasta de backup no formato esperado (`backup-YYYY-MM-DD-HH-MM-SS`)
|
|
257
|
+
4. Copia o arquivo para a pasta criada
|
|
258
|
+
5. Deixa o backup pronto para ser encontrado pelo comando `restore`
|
|
259
|
+
|
|
260
|
+
**Exemplo completo:**
|
|
261
|
+
```bash
|
|
262
|
+
# 1. Baixar backup do Dashboard do Supabase
|
|
263
|
+
# Arquivo: db_cluster-04-03-2024@14-16-59.backup.gz
|
|
264
|
+
|
|
265
|
+
# 2. Importar o arquivo
|
|
266
|
+
npx smoonb import --file "C:\Downloads\db_cluster-04-03-2024@14-16-59.backup.gz"
|
|
267
|
+
|
|
268
|
+
# 3. Restaurar o backup importado
|
|
269
|
+
npx smoonb restore
|
|
270
|
+
# O backup importado aparecerá na lista de backups disponíveis
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Importante:**
|
|
274
|
+
- O arquivo deve estar no formato do Dashboard: `db_cluster-DD-MM-YYYY@HH-MM-SS.backup.gz`
|
|
275
|
+
- O caminho pode ser absoluto ou relativo
|
|
276
|
+
- O comando criará a estrutura de pastas necessária automaticamente
|
|
277
|
+
|
|
245
278
|
### Verificação Pós-Restore
|
|
246
279
|
|
|
247
280
|
```bash
|
|
@@ -263,6 +296,7 @@ npx smoonb check
|
|
|
263
296
|
|---------|-----------|
|
|
264
297
|
| `npx smoonb backup` | Backup completo interativo usando Docker |
|
|
265
298
|
| `npx smoonb restore` | Restauração interativa usando psql (Docker) |
|
|
299
|
+
| `npx smoonb import --file <path>` | Importar arquivo .backup.gz do Dashboard do Supabase |
|
|
266
300
|
| `npx smoonb check` | Verificação de integridade pós-restore |
|
|
267
301
|
|
|
268
302
|
## 🏗️ Arquitetura Técnica
|
package/bin/smoonb.js
CHANGED
|
@@ -23,11 +23,14 @@ const program = new Command();
|
|
|
23
23
|
// Configuração básica do programa
|
|
24
24
|
program
|
|
25
25
|
.name('smoonb')
|
|
26
|
-
.description('Complete Supabase backup and migration tool
|
|
26
|
+
.description('Complete Supabase backup and migration tool')
|
|
27
27
|
.version(packageJson.version, '-v, --version', 'display version number')
|
|
28
28
|
.addHelpText('before', () => {
|
|
29
29
|
showBetaBanner();
|
|
30
|
-
return ''
|
|
30
|
+
return chalk.yellow.bold('\n⚠️ TERMO DE USO E AVISO DE RISCO\n') +
|
|
31
|
+
chalk.white('Ao prosseguir, você reconhece e concorda que o Supa Moonbase (smoonb) é fornecido "NO ESTADO EM QUE SE ENCONTRA" ("AS IS") e "CONFORME DISPONIBILIDADE", sem garantias de qualquer natureza—expressas, implícitas ou legais—incluindo, sem limitação, garantias de comercialização, adequação a um fim específico e não violação, na máxima extensão permitida pela lei aplicável. Operações de backup e restauração envolvem riscos, os ambientes variam amplamente e não é possível prever ou validar todas as configurações dos usuários. Você é o único responsável por validar seu ambiente, manter cópias independentes e verificar os resultados antes de utilizá-los em produção. O Supa Moonbase (smoonb) é construído com repositórios públicos, auditáveis e software livre, para auxiliar pessoas a simplificar seus fluxos, sem com isso criar qualquer garantia, promessa de suporte ou compromisso de nível de serviço.\n\n') +
|
|
32
|
+
chalk.white('Limitação de responsabilidade (PT-BR) — Na máxima extensão permitida por lei, a Goalmoon, seus contribuidores e licenciadores não serão responsáveis por danos indiretos, incidentais, especiais, consequentes, exemplares ou punitivos (incluindo perda de dados, interrupção de negócios ou lucros cessantes) decorrentes do uso, incapacidade de uso, das operações de backup/restauração realizadas com, ou dos resultados gerados pelo Supa Moonbase (smoonb). Em qualquer hipótese, a responsabilidade total por todas as reivindicações relacionadas ao Supa Moonbase (smoonb) não excederá o valor pago por você pelo Supa Moonbase (smoonb) nos 12 meses anteriores ao evento. Nada neste aviso exclui ou limita responsabilidades onde tais limites sejam proibidos por lei, incluindo (conforme aplicável) dolo ou culpa grave.\n\n') +
|
|
33
|
+
chalk.white('Observação para consumidores no Brasil (PT-BR) — Para consumidores brasileiros, este aviso não afasta direitos irrenunciáveis previstos no Código de Defesa do Consumidor (CDC); qualquer limitação aqui prevista só se aplica nos limites da lei e não impede a indenização obrigatória quando cabível.\n\n');
|
|
31
34
|
})
|
|
32
35
|
.addHelpText('after', () => {
|
|
33
36
|
return chalk.cyan.bold(`
|
|
@@ -60,6 +63,14 @@ program
|
|
|
60
63
|
.option('-o, --output <file>', 'Arquivo de saída do relatório', 'check-report.json')
|
|
61
64
|
.action(commands.check);
|
|
62
65
|
|
|
66
|
+
program
|
|
67
|
+
.command('import')
|
|
68
|
+
.description('Importar arquivo .backup.gz do Dashboard do Supabase')
|
|
69
|
+
.requiredOption('-f, --file <path>', 'Caminho completo do arquivo .backup.gz a importar')
|
|
70
|
+
.action(async (options) => {
|
|
71
|
+
await commands.import({ file: options.file });
|
|
72
|
+
});
|
|
73
|
+
|
|
63
74
|
// Tratamento de erros
|
|
64
75
|
program.on('command:*', function (operands) {
|
|
65
76
|
console.error(chalk.red.bold('❌ Comando não reconhecido:'), operands[0]);
|
package/package.json
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs').promises;
|
|
4
|
+
const { ensureDir } = require('../utils/fsx');
|
|
5
|
+
const { readEnvFile } = require('../utils/env');
|
|
6
|
+
const { showBetaBanner } = require('../utils/banner');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Comando para importar arquivo .backup.gz do Dashboard do Supabase
|
|
10
|
+
*/
|
|
11
|
+
module.exports = async (options) => {
|
|
12
|
+
showBetaBanner();
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
// Validar que o arquivo foi fornecido
|
|
16
|
+
if (!options.file) {
|
|
17
|
+
console.error(chalk.red('❌ Arquivo não fornecido'));
|
|
18
|
+
console.log(chalk.yellow('💡 Use: npx smoonb --import --file <caminho-completo-do-arquivo>'));
|
|
19
|
+
console.log(chalk.gray(' Exemplo: npx smoonb --import --file "C:\\Downloads\\db_cluster-04-03-2024@14-16-59.backup.gz"'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const sourceFile = path.resolve(options.file);
|
|
24
|
+
|
|
25
|
+
// Verificar se o arquivo existe
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(sourceFile);
|
|
28
|
+
} catch {
|
|
29
|
+
console.error(chalk.red(`❌ Arquivo não encontrado: ${sourceFile}`));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Verificar se é um arquivo .backup.gz
|
|
34
|
+
if (!sourceFile.endsWith('.backup.gz') && !sourceFile.endsWith('.backup')) {
|
|
35
|
+
console.error(chalk.red('❌ Arquivo deve ser .backup.gz ou .backup'));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Ler .env.local para obter SMOONB_OUTPUT_DIR
|
|
40
|
+
const envPath = path.join(process.cwd(), '.env.local');
|
|
41
|
+
let outputDir = './backups';
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const currentEnv = await readEnvFile(envPath);
|
|
45
|
+
outputDir = currentEnv.SMOONB_OUTPUT_DIR || './backups';
|
|
46
|
+
} catch {
|
|
47
|
+
// Se não conseguir ler .env.local, usar padrão
|
|
48
|
+
console.log(chalk.yellow('⚠️ Não foi possível ler .env.local, usando diretório padrão: ./backups'));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Extrair informações do nome do arquivo
|
|
52
|
+
// Formato esperado: db_cluster-DD-MM-YYYY@HH-MM-SS.backup.gz
|
|
53
|
+
const fileName = path.basename(sourceFile);
|
|
54
|
+
const match = fileName.match(/db_cluster-(\d{2})-(\d{2})-(\d{4})@(\d{2})-(\d{2})-(\d{2})\.backup(\.gz)?/);
|
|
55
|
+
|
|
56
|
+
if (!match) {
|
|
57
|
+
console.error(chalk.red('❌ Nome do arquivo não está no formato esperado do Dashboard'));
|
|
58
|
+
console.log(chalk.yellow('💡 Formato esperado: db_cluster-DD-MM-YYYY@HH-MM-SS.backup.gz'));
|
|
59
|
+
console.log(chalk.gray(` Arquivo recebido: ${fileName}`));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const [, day, month, year, hour, minute, second] = match;
|
|
64
|
+
|
|
65
|
+
// Criar nome da pasta no formato backup-YYYY-MM-DD-HH-MM-SS
|
|
66
|
+
const backupDirName = `backup-${year}-${month}-${day}-${hour}-${minute}-${second}`;
|
|
67
|
+
const backupDir = path.join(outputDir, backupDirName);
|
|
68
|
+
|
|
69
|
+
// Criar diretório de backup
|
|
70
|
+
await ensureDir(backupDir);
|
|
71
|
+
console.log(chalk.blue(`📁 Criando diretório de backup: ${backupDirName}`));
|
|
72
|
+
|
|
73
|
+
// Copiar arquivo para o diretório de backup
|
|
74
|
+
const destFile = path.join(backupDir, fileName);
|
|
75
|
+
await fs.copyFile(sourceFile, destFile);
|
|
76
|
+
|
|
77
|
+
// Obter tamanho do arquivo
|
|
78
|
+
const stats = await fs.stat(destFile);
|
|
79
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
80
|
+
|
|
81
|
+
console.log(chalk.green(`✅ Arquivo importado com sucesso!`));
|
|
82
|
+
console.log(chalk.blue(`📁 Localização: ${backupDir}`));
|
|
83
|
+
console.log(chalk.blue(`📦 Arquivo: ${fileName} (${sizeMB} MB)`));
|
|
84
|
+
console.log(chalk.cyan(`\n💡 Próximo passo: Execute 'npx smoonb restore' para restaurar este backup`));
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error(chalk.red(`❌ Erro ao importar arquivo: ${error.message}`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
package/src/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const { showBetaBanner } = require('./utils/banner');
|
|
|
13
13
|
const backupCommand = require('./commands/backup');
|
|
14
14
|
const restoreCommand = require('./commands/restore');
|
|
15
15
|
const checkCommand = require('./commands/check');
|
|
16
|
+
const importCommand = require('./commands/import');
|
|
16
17
|
|
|
17
18
|
// Exportar utilitários
|
|
18
19
|
const supabaseUtils = require('./utils/supabase');
|
|
@@ -218,7 +219,8 @@ module.exports = {
|
|
|
218
219
|
commands: {
|
|
219
220
|
backup: backupCommand,
|
|
220
221
|
restore: restoreCommand,
|
|
221
|
-
check: checkCommand
|
|
222
|
+
check: checkCommand,
|
|
223
|
+
import: importCommand
|
|
222
224
|
},
|
|
223
225
|
|
|
224
226
|
// Utilitários
|