smoonb 0.0.54 → 0.0.55

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smoonb",
3
- "version": "0.0.54",
3
+ "version": "0.0.55",
4
4
  "description": "Complete Supabase backup and migration tool - EXPERIMENTAL VERSION - USE AT YOUR OWN RISK",
5
5
  "preferGlobal": false,
6
6
  "preventGlobalInstall": true,
@@ -196,8 +196,10 @@ module.exports = async (options) => {
196
196
  console.log(chalk.gray(`🐳 Backup via Docker Desktop`));
197
197
 
198
198
  // Contar etapas totais para numeração
199
+ // Etapas fixas: Database, Database Separado, Database Settings, Custom Roles (4)
200
+ // Etapas condicionais: Auth, Realtime, Storage, Functions, Temp, Migrations
199
201
  let stepNumber = 0;
200
- const totalSteps = 7 + (flags?.includeAuth ? 1 : 0) + (flags?.includeRealtime ? 1 : 0) + (flags?.includeStorage ? 1 : 0) + (flags?.includeFunctions ? 1 : 0) + (flags?.includeTemp ? 1 : 0) + (flags?.includeMigrations ? 1 : 0);
202
+ const totalSteps = 4 + (flags?.includeAuth ? 1 : 0) + (flags?.includeRealtime ? 1 : 0) + (flags?.includeStorage ? 1 : 0) + (flags?.includeFunctions ? 1 : 0) + (flags?.includeTemp ? 1 : 0) + (flags?.includeMigrations ? 1 : 0);
201
203
 
202
204
  // 1. Backup Database via pg_dumpall Docker
203
205
  stepNumber++;
@@ -8,7 +8,7 @@ const { showDockerMessagesAndExit } = require('../utils');
8
8
  */
9
9
  module.exports = async () => {
10
10
  console.log(chalk.blue('\n🐳 Validação Docker...'));
11
- console.log(chalk.gray('🔍 Verificando dependências Docker...'));
11
+ console.log(chalk.cyan('🔍 Verificando dependências Docker...'));
12
12
 
13
13
  const backupCapability = await canPerformCompleteBackup();
14
14
 
@@ -18,10 +18,43 @@ module.exports = async (context) => {
18
18
  const dbPassword = extractPasswordFromDbUrl(databaseUrl);
19
19
  await ensureCleanLink(projectId, accessToken, dbPassword);
20
20
 
21
- // Limpar pasta supabase/functions antes do backup
21
+ // Preparar diretório supabase/functions (criar se não existir, mas não limpar ainda)
22
22
  const supabaseFunctionsDir = path.join(process.cwd(), 'supabase', 'functions');
23
- await cleanDir(supabaseFunctionsDir);
24
- console.log(chalk.gray(' - Pasta supabase/functions limpa.'));
23
+
24
+ // Verificar flag de limpeza antes do backup
25
+ const shouldCleanAfter = context?.cleanupFlags?.cleanFunctions || false;
26
+
27
+ // Registrar funções que já existiam ANTES do processo (para preservar se necessário)
28
+ let existingFunctionsBefore = [];
29
+ try {
30
+ const existingItems = await fs.readdir(supabaseFunctionsDir);
31
+ for (const item of existingItems) {
32
+ const itemPath = path.join(supabaseFunctionsDir, item);
33
+ const stats = await fs.stat(itemPath);
34
+ if (stats.isDirectory()) {
35
+ existingFunctionsBefore.push(item);
36
+ }
37
+ }
38
+ } catch {
39
+ // Diretório não existe, tudo bem
40
+ existingFunctionsBefore = [];
41
+ }
42
+
43
+ // Se o usuário escolheu limpar APÓS, podemos limpar ANTES também para garantir ambiente limpo
44
+ // Mas se escolheu NÃO limpar, preservamos o que já existe
45
+ if (shouldCleanAfter) {
46
+ // Limpar antes se o usuário escolheu limpar após (garante ambiente limpo)
47
+ await cleanDir(supabaseFunctionsDir);
48
+ console.log(chalk.gray(' - Pasta supabase/functions limpa antes do backup.'));
49
+ } else {
50
+ // Apenas garantir que o diretório existe
51
+ await fs.mkdir(supabaseFunctionsDir, { recursive: true });
52
+ if (existingFunctionsBefore.length > 0) {
53
+ console.log(chalk.gray(` - Preservando ${existingFunctionsBefore.length} função(ões) existente(s) na pasta supabase/functions.`));
54
+ } else {
55
+ console.log(chalk.gray(' - Pasta supabase/functions preparada (será preservada após backup).'));
56
+ }
57
+ }
25
58
 
26
59
  console.log(chalk.gray(' - Listando Edge Functions via Management API...'));
27
60
 
@@ -99,12 +132,16 @@ module.exports = async (context) => {
99
132
  console.log(chalk.yellow(` ⚠️ Nenhum arquivo encontrado em ${tempDownloadDir}`));
100
133
  }
101
134
 
102
- // LIMPAR supabase/functions após copiar
103
- try {
104
- await fs.rm(tempDownloadDir, { recursive: true, force: true });
105
- } catch {
106
- // Ignorar erro de limpeza
135
+ // Limpar função baixada temporariamente APENAS se o usuário escolheu limpar após
136
+ // Se não escolheu, preservar (pode ser que já existisse antes)
137
+ if (shouldCleanAfter) {
138
+ try {
139
+ await fs.rm(tempDownloadDir, { recursive: true, force: true });
140
+ } catch {
141
+ // Ignorar erro de limpeza
142
+ }
107
143
  }
144
+ // Se shouldCleanAfter = false, manter a função baixada (e qualquer função que já existia)
108
145
 
109
146
  console.log(chalk.green(` ✅ ${func.name} baixada com sucesso`));
110
147
  successCount++;
@@ -126,12 +163,15 @@ module.exports = async (context) => {
126
163
  console.log(chalk.green(` ✅ Sucessos: ${successCount}`));
127
164
  console.log(chalk.green(` ❌ Erros: ${errorCount}`));
128
165
 
129
- // Usar flag de limpeza do contexto (já foi perguntado no início)
130
- const shouldClean = context?.cleanupFlags?.cleanFunctions || false;
131
-
132
- if (shouldClean) {
166
+ // Limpar pasta supabase/functions APÓS o backup apenas se o usuário escolheu
167
+ // Nota: shouldCleanAfter foi definido acima
168
+ if (shouldCleanAfter) {
133
169
  await cleanDir(supabaseFunctionsDir);
134
- console.log(chalk.gray(' - supabase/functions limpo.'));
170
+ console.log(chalk.gray(' - supabase/functions limpo após o backup.'));
171
+ } else {
172
+ // Preservar tudo: tanto as funções que já existiam quanto as que foram baixadas
173
+ // As funções baixadas não foram removidas individualmente (linha acima foi ajustada)
174
+ console.log(chalk.gray(' - supabase/functions preservada conforme solicitado.'));
135
175
  }
136
176
 
137
177
  return {
@@ -49,8 +49,8 @@ module.exports = async ({ backupFilePath, targetDatabaseUrl }) => {
49
49
  `-f /host/${uncompressedFile}`
50
50
  ].join(' ');
51
51
 
52
- console.log(chalk.gray(' - Executando psql via Docker...'));
53
- console.log(chalk.gray(' ℹ️ Seguindo documentação oficial Supabase'));
52
+ console.log(chalk.cyan(' - Executando psql via Docker...'));
53
+ console.log(chalk.cyan(' ℹ️ Seguindo documentação oficial Supabase'));
54
54
  console.log(chalk.yellow(' ⚠️ AVISO: Erros como "object already exists" são ESPERADOS'));
55
55
  console.log(chalk.yellow(' ⚠️ Isto acontece porque o backup contém CREATE para todos os schemas'));
56
56
  console.log(chalk.yellow(' ⚠️ Supabase já tem auth e storage criados, então esses erros são normais'));
@@ -40,8 +40,8 @@ module.exports = async ({ backupPath, targetProject }) => {
40
40
  // Criar diretório supabase/functions se não existir
41
41
  await fs.mkdir(supabaseFunctionsDir, { recursive: true });
42
42
 
43
- // Limpar supabase/functions antes de copiar
44
- console.log(chalk.gray(' - Limpando supabase/functions...'));
43
+ // Limpar supabase/functions antes de copiar (necessário para garantir ambiente limpo)
44
+ console.log(chalk.cyan(' - Limpando supabase/functions antes de copiar...'));
45
45
  try {
46
46
  await fs.rm(supabaseFunctionsDir, { recursive: true, force: true });
47
47
  await fs.mkdir(supabaseFunctionsDir, { recursive: true });
@@ -95,8 +95,8 @@ module.exports = async ({ backupPath, targetProject }) => {
95
95
  }
96
96
  }
97
97
 
98
- // Limpar supabase/functions após deploy
99
- console.log(chalk.gray(' - Limpando supabase/functions após deploy...'));
98
+ // Limpar supabase/functions após deploy (arquivos temporários não são mais necessários)
99
+ console.log(chalk.cyan(' - Limpando supabase/functions após deploy...'));
100
100
  try {
101
101
  await fs.rm(supabaseFunctionsDir, { recursive: true, force: true });
102
102
  } catch {