smoonb 0.0.54 → 0.0.56

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.56",
4
4
  "description": "Complete Supabase backup and migration tool - EXPERIMENTAL VERSION - USE AT YOUR OWN RISK",
5
5
  "preferGlobal": false,
6
6
  "preventGlobalInstall": true,
@@ -139,22 +139,22 @@ module.exports = async (options) => {
139
139
 
140
140
  // Mostrar resumo e pedir confirmação final
141
141
  console.log(chalk.cyan('\n📋 RESUMO DAS CONFIGURAÇÕES:\n'));
142
- console.log(chalk.gray(` ✅ Edge Functions: ${flags.includeFunctions ? 'Sim' : 'Não'}`));
142
+ console.log(chalk.white(` ✅ Edge Functions: ${flags.includeFunctions ? 'Sim' : 'Não'}`));
143
143
  if (flags.includeFunctions) {
144
- console.log(chalk.gray(` 🗑️ Limpar após backup: ${flags.cleanFunctions ? 'Sim' : 'Não'}`));
144
+ console.log(chalk.white(` 🗑️ Limpar após backup: ${flags.cleanFunctions ? 'Sim' : 'Não'}`));
145
145
  }
146
- console.log(chalk.gray(` ✅ Supabase .temp: ${flags.includeTemp ? 'Sim' : 'Não'}`));
146
+ console.log(chalk.white(` ✅ Supabase .temp: ${flags.includeTemp ? 'Sim' : 'Não'}`));
147
147
  if (flags.includeTemp) {
148
- console.log(chalk.gray(` 🗑️ Apagar após backup: ${flags.cleanTemp ? 'Sim' : 'Não'}`));
148
+ console.log(chalk.white(` 🗑️ Apagar após backup: ${flags.cleanTemp ? 'Sim' : 'Não'}`));
149
149
  }
150
- console.log(chalk.gray(` ✅ Migrations: ${flags.includeMigrations ? 'Sim' : 'Não'}`));
150
+ console.log(chalk.white(` ✅ Migrations: ${flags.includeMigrations ? 'Sim' : 'Não'}`));
151
151
  if (flags.includeMigrations) {
152
- console.log(chalk.gray(` 🗑️ Apagar após backup: ${flags.cleanMigrations ? 'Sim' : 'Não'}`));
152
+ console.log(chalk.white(` 🗑️ Apagar após backup: ${flags.cleanMigrations ? 'Sim' : 'Não'}`));
153
153
  }
154
- console.log(chalk.gray(` ✅ Storage: ${flags.includeStorage ? 'Sim' : 'Não'}`));
155
- console.log(chalk.gray(` ✅ Auth: ${flags.includeAuth ? 'Sim' : 'Não'}`));
156
- console.log(chalk.gray(` ✅ Realtime: ${flags.includeRealtime ? 'Sim' : 'Não'}`));
157
- console.log(chalk.gray(` 📁 Diretório de backup: ${finalBackupDir}\n`));
154
+ console.log(chalk.white(` ✅ Storage: ${flags.includeStorage ? 'Sim' : 'Não'}`));
155
+ console.log(chalk.white(` ✅ Auth: ${flags.includeAuth ? 'Sim' : 'Não'}`));
156
+ console.log(chalk.white(` ✅ Realtime: ${flags.includeRealtime ? 'Sim' : 'Não'}`));
157
+ console.log(chalk.white(` 📁 Diretório de backup: ${finalBackupDir}\n`));
158
158
 
159
159
  const finalOk = await confirm('Deseja iniciar o backup com estas configurações?', true);
160
160
 
@@ -193,11 +193,13 @@ module.exports = async (options) => {
193
193
 
194
194
  // Executar todas as etapas na ordem
195
195
  console.log(chalk.blue(`📁 Diretório: ${finalBackupDir}`));
196
- console.log(chalk.gray(`🐳 Backup via Docker Desktop`));
196
+ console.log(chalk.white(`🐳 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
 
@@ -17,7 +17,7 @@ module.exports = async () => {
17
17
  }
18
18
 
19
19
  console.log(chalk.green('✅ Docker Desktop detectado e funcionando'));
20
- console.log(chalk.gray(`🐳 Versão: ${backupCapability.dockerStatus.version}`));
20
+ console.log(chalk.white(`🐳 Versão: ${backupCapability.dockerStatus.version}`));
21
21
 
22
22
  return { success: true };
23
23
  };
@@ -8,7 +8,7 @@ const { execSync } = require('child_process');
8
8
  */
9
9
  module.exports = async ({ databaseUrl, backupDir }) => {
10
10
  try {
11
- console.log(chalk.gray(' - Criando backup completo via pg_dumpall...'));
11
+ console.log(chalk.white(' - Criando backup completo via pg_dumpall...'));
12
12
 
13
13
  // Extrair credenciais da databaseUrl
14
14
  const urlMatch = databaseUrl.match(/postgresql:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)/);
@@ -45,7 +45,7 @@ module.exports = async ({ databaseUrl, backupDir }) => {
45
45
  `-f /host/${fileName}`
46
46
  ].join(' ');
47
47
 
48
- console.log(chalk.gray(' - Executando pg_dumpall via Docker...'));
48
+ console.log(chalk.white(' - Executando pg_dumpall via Docker...'));
49
49
  execSync(dockerCmd, { stdio: 'pipe' });
50
50
 
51
51
  // Compactar igual ao Supabase Dashboard
@@ -8,14 +8,14 @@ const { execSync } = require('child_process');
8
8
  */
9
9
  module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
10
10
  try {
11
- console.log(chalk.gray(' - Criando backups SQL separados via Supabase CLI...'));
11
+ console.log(chalk.white(' - Criando backups SQL separados via Supabase CLI...'));
12
12
 
13
13
  const dbUrl = databaseUrl;
14
14
  const files = [];
15
15
  let totalSizeKB = 0;
16
16
 
17
17
  // 1. Backup do Schema
18
- console.log(chalk.gray(' - Exportando schema...'));
18
+ console.log(chalk.white(' - Exportando schema...'));
19
19
  const schemaFile = path.join(backupDir, 'schema.sql');
20
20
 
21
21
  try {
@@ -33,7 +33,7 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
33
33
  }
34
34
 
35
35
  // 2. Backup dos Dados
36
- console.log(chalk.gray(' - Exportando dados...'));
36
+ console.log(chalk.white(' - Exportando dados...'));
37
37
  const dataFile = path.join(backupDir, 'data.sql');
38
38
 
39
39
  try {
@@ -51,7 +51,7 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
51
51
  }
52
52
 
53
53
  // 3. Backup dos Roles
54
- console.log(chalk.gray(' - Exportando roles...'));
54
+ console.log(chalk.white(' - Exportando roles...'));
55
55
  const rolesFile = path.join(backupDir, 'roles.sql');
56
56
 
57
57
  try {
@@ -8,7 +8,7 @@ const { execSync } = require('child_process');
8
8
  */
9
9
  module.exports = async ({ databaseUrl, projectId, backupDir }) => {
10
10
  try {
11
- console.log(chalk.gray(' - Capturando Database Extensions and Settings...'));
11
+ console.log(chalk.white(' - Capturando Database Extensions and Settings...'));
12
12
 
13
13
  // Extrair credenciais da databaseUrl
14
14
  const urlMatch = databaseUrl.match(/postgresql:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)/);
@@ -125,7 +125,7 @@ AND EXISTS (
125
125
  '-A' // Unaligned output
126
126
  ].join(' ');
127
127
 
128
- console.log(chalk.gray(' - Executando queries de configurações via Docker...'));
128
+ console.log(chalk.white(' - Executando queries de configurações via Docker...'));
129
129
  const output = execSync(dockerCmd, { stdio: 'pipe', encoding: 'utf8' });
130
130
 
131
131
  // Processar output e criar JSON estruturado
@@ -7,7 +7,7 @@ const { writeJson } = require('../../../utils/fsx');
7
7
  */
8
8
  module.exports = async ({ projectId, accessToken, backupDir }) => {
9
9
  try {
10
- console.log(chalk.gray(' - Exportando configurações de Auth via Management API...'));
10
+ console.log(chalk.white(' - Exportando configurações de Auth via Management API...'));
11
11
 
12
12
  // Usar fetch direto para Management API com Personal Access Token
13
13
  const authResponse = await fetch(`https://api.supabase.com/v1/projects/${projectId}/config/auth`, {
@@ -8,7 +8,7 @@ const { captureRealtimeSettings } = require('../../../utils/realtime-settings');
8
8
  */
9
9
  module.exports = async ({ projectId, backupDir, options }) => {
10
10
  try {
11
- console.log(chalk.gray(' - Capturando Realtime Settings interativamente...'));
11
+ console.log(chalk.white(' - Capturando Realtime Settings interativamente...'));
12
12
 
13
13
  const result = await captureRealtimeSettings(projectId, backupDir, options?.skipRealtime);
14
14
 
@@ -10,7 +10,7 @@ module.exports = async ({ projectId, accessToken, backupDir }) => {
10
10
  const storageDir = path.join(backupDir, 'storage');
11
11
  await ensureDir(storageDir);
12
12
 
13
- console.log(chalk.gray(' - Listando buckets de Storage via Management API...'));
13
+ console.log(chalk.white(' - Listando buckets de Storage via Management API...'));
14
14
 
15
15
  // Usar fetch direto para Management API com Personal Access Token
16
16
  const storageResponse = await fetch(`https://api.supabase.com/v1/projects/${projectId}/storage/buckets`, {
@@ -28,20 +28,20 @@ module.exports = async ({ projectId, accessToken, backupDir }) => {
28
28
  const buckets = await storageResponse.json();
29
29
 
30
30
  if (!buckets || buckets.length === 0) {
31
- console.log(chalk.gray(' - Nenhum bucket encontrado'));
31
+ console.log(chalk.white(' - Nenhum bucket encontrado'));
32
32
  await writeJson(path.join(storageDir, 'README.md'), {
33
33
  message: 'Nenhum bucket de Storage encontrado neste projeto'
34
34
  });
35
35
  return { success: true, buckets: [] };
36
36
  }
37
37
 
38
- console.log(chalk.gray(` - Encontrados ${buckets.length} buckets`));
38
+ console.log(chalk.white(` - Encontrados ${buckets.length} buckets`));
39
39
 
40
40
  const processedBuckets = [];
41
41
 
42
42
  for (const bucket of buckets || []) {
43
43
  try {
44
- console.log(chalk.gray(` - Processando bucket: ${bucket.name}`));
44
+ console.log(chalk.white(` - Processando bucket: ${bucket.name}`));
45
45
 
46
46
  // Listar objetos do bucket via Management API com Personal Access Token
47
47
  const objectsResponse = await fetch(`https://api.supabase.com/v1/projects/${projectId}/storage/buckets/${bucket.name}/objects`, {
@@ -11,7 +11,7 @@ const execAsync = promisify(exec);
11
11
  */
12
12
  module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
13
13
  try {
14
- console.log(chalk.gray(' - Exportando Custom Roles via Docker...'));
14
+ console.log(chalk.white(' - Exportando Custom Roles via Docker...'));
15
15
 
16
16
  const customRolesFile = path.join(backupDir, 'custom-roles.sql');
17
17
 
@@ -18,12 +18,45 @@ 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.white(' - 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.white(` - Preservando ${existingFunctionsBefore.length} função(ões) existente(s) na pasta supabase/functions.`));
54
+ } else {
55
+ console.log(chalk.white(' - Pasta supabase/functions preparada (será preservada após backup).'));
56
+ }
57
+ }
25
58
 
26
- console.log(chalk.gray(' - Listando Edge Functions via Management API...'));
59
+ console.log(chalk.white(' - Listando Edge Functions via Management API...'));
27
60
 
28
61
  // Usar fetch direto para Management API com Personal Access Token
29
62
  const functionsResponse = await fetch(`https://api.supabase.com/v1/projects/${projectId}/functions`, {
@@ -41,14 +74,14 @@ module.exports = async (context) => {
41
74
  const functions = await functionsResponse.json();
42
75
 
43
76
  if (!functions || functions.length === 0) {
44
- console.log(chalk.gray(' - Nenhuma Edge Function encontrada'));
77
+ console.log(chalk.white(' - Nenhuma Edge Function encontrada'));
45
78
  await writeJson(path.join(functionsDir, 'README.md'), {
46
79
  message: 'Nenhuma Edge Function encontrada neste projeto'
47
80
  });
48
81
  return { success: true, reason: 'no_functions', functions: [] };
49
82
  }
50
83
 
51
- console.log(chalk.gray(` - Encontradas ${functions.length} Edge Function(s)`));
84
+ console.log(chalk.white(` - Encontradas ${functions.length} Edge Function(s)`));
52
85
 
53
86
  const downloadedFunctions = [];
54
87
  let successCount = 0;
@@ -58,7 +91,7 @@ module.exports = async (context) => {
58
91
  // Nota: O CLI ignora o cwd e sempre baixa para supabase/functions
59
92
  for (const func of functions) {
60
93
  try {
61
- console.log(chalk.gray(` - Baixando: ${func.name}...`));
94
+ console.log(chalk.white(` - Baixando: ${func.name}...`));
62
95
 
63
96
  // Criar diretório da função NO BACKUP
64
97
  const functionTargetDir = path.join(functionsDir, func.name);
@@ -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.white(' - 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.white(' - supabase/functions preservada conforme solicitado.'));
135
175
  }
136
176
 
137
177
  return {
@@ -14,10 +14,10 @@ module.exports = async (context) => {
14
14
 
15
15
  const fileCount = await copyDirSafe(tempDir, backupTempDir);
16
16
 
17
- console.log(chalk.gray(` - Copiando supabase/.temp → backups/backup-${path.basename(backupDir)}/supabase-temp (${fileCount} arquivos)...`));
17
+ console.log(chalk.white(` - Copiando supabase/.temp → backups/backup-${path.basename(backupDir)}/supabase-temp (${fileCount} arquivos)...`));
18
18
 
19
19
  if (fileCount === 0) {
20
- console.log(chalk.gray(' - Nenhum arquivo encontrado em supabase/.temp'));
20
+ console.log(chalk.white(' - Nenhum arquivo encontrado em supabase/.temp'));
21
21
  } else {
22
22
  console.log(chalk.green(` ✅ ${fileCount} arquivo(s) copiado(s)`));
23
23
  }
@@ -27,7 +27,7 @@ module.exports = async (context) => {
27
27
 
28
28
  if (shouldClean) {
29
29
  await cleanDir(tempDir);
30
- console.log(chalk.gray(' - supabase/.temp apagado.'));
30
+ console.log(chalk.white(' - supabase/.temp apagado.'));
31
31
  }
32
32
 
33
33
  return {
@@ -17,10 +17,10 @@ module.exports = async (context) => {
17
17
  // Limpar migrations local (opcional, mas recomendado para garantir servidor como fonte da verdade)
18
18
  const migrationsDir = path.join(process.cwd(), 'supabase', 'migrations');
19
19
  await cleanDir(migrationsDir);
20
- console.log(chalk.gray(' - Limpando supabase/migrations...'));
20
+ console.log(chalk.white(' - Limpando supabase/migrations...'));
21
21
 
22
22
  // Baixar todas as migrations do servidor usando migration fetch
23
- console.log(chalk.gray(' - Baixando todas as migrations do servidor usando migration fetch...'));
23
+ console.log(chalk.white(' - Baixando todas as migrations do servidor usando migration fetch...'));
24
24
 
25
25
  const env = {
26
26
  ...process.env,
@@ -43,12 +43,12 @@ module.exports = async (context) => {
43
43
 
44
44
  // Contar arquivos baixados
45
45
  const fileCount = await countFiles(migrationsDir);
46
- console.log(chalk.gray(` - Arquivos baixados: ${fileCount} migrations`));
46
+ console.log(chalk.white(` - Arquivos baixados: ${fileCount} migrations`));
47
47
 
48
48
  // Copiar migrations para o backup
49
49
  const backupMigrationsDir = path.join(backupDir, 'migrations');
50
50
  const copiedCount = await copyDirSafe(migrationsDir, backupMigrationsDir);
51
- console.log(chalk.gray(` - Copiando supabase/migrations → backups/backup-${path.basename(backupDir)}/migrations (${copiedCount} arquivos)...`));
51
+ console.log(chalk.white(` - Copiando supabase/migrations → backups/backup-${path.basename(backupDir)}/migrations (${copiedCount} arquivos)...`));
52
52
 
53
53
  if (copiedCount > 0) {
54
54
  console.log(chalk.green(` ✅ ${copiedCount} migration(s) copiada(s)`));
@@ -13,8 +13,8 @@ module.exports = async ({ backupFilePath, targetDatabaseUrl }) => {
13
13
 
14
14
  // Verificar se é arquivo .backup.gz (compactado) ou .backup (descompactado)
15
15
  if (fileName.endsWith('.backup.gz')) {
16
- console.log(chalk.gray(' - Arquivo .backup.gz detectado'));
17
- console.log(chalk.gray(' - Extraindo arquivo .gz...'));
16
+ console.log(chalk.white(' - Arquivo .backup.gz detectado'));
17
+ console.log(chalk.white(' - Extraindo arquivo .gz...'));
18
18
 
19
19
  const unzipCmd = [
20
20
  'docker run --rm',
@@ -24,10 +24,10 @@ module.exports = async ({ backupFilePath, targetDatabaseUrl }) => {
24
24
 
25
25
  execSync(unzipCmd, { stdio: 'pipe' });
26
26
  uncompressedFile = fileName.replace('.gz', '');
27
- console.log(chalk.gray(' - Arquivo descompactado: ' + uncompressedFile));
27
+ console.log(chalk.white(' - Arquivo descompactado: ' + uncompressedFile));
28
28
  } else if (fileName.endsWith('.backup')) {
29
- console.log(chalk.gray(' - Arquivo .backup detectado (já descompactado)'));
30
- console.log(chalk.gray(' - Prosseguindo com restauração direta'));
29
+ console.log(chalk.white(' - Arquivo .backup detectado (já descompactado)'));
30
+ console.log(chalk.white(' - Prosseguindo com restauração direta'));
31
31
  } else {
32
32
  throw new Error(`Formato de arquivo inválido. Esperado .backup.gz ou .backup, recebido: ${fileName}`);
33
33
  }
@@ -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'));
@@ -32,7 +32,7 @@ module.exports = async ({ backupPath, targetProject }) => {
32
32
  return { success: false, functions_count: 0, success_count: 0 };
33
33
  }
34
34
 
35
- console.log(chalk.gray(` - Encontradas ${functions.length} Edge Function(s)`));
35
+ console.log(chalk.white(` - Encontradas ${functions.length} Edge Function(s)`));
36
36
 
37
37
  // COPIAR Edge Functions de backups/backup-XXX/edge-functions para supabase/functions
38
38
  const supabaseFunctionsDir = path.join(process.cwd(), 'supabase', 'functions');
@@ -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 });
@@ -54,13 +54,13 @@ module.exports = async ({ backupPath, targetProject }) => {
54
54
  const backupFuncPath = path.join(edgeFunctionsDir, funcName);
55
55
  const targetFuncPath = path.join(supabaseFunctionsDir, funcName);
56
56
 
57
- console.log(chalk.gray(` - Copiando ${funcName} para supabase/functions...`));
57
+ console.log(chalk.white(` - Copiando ${funcName} para supabase/functions...`));
58
58
 
59
59
  // Copiar recursivamente
60
60
  await copyDirectoryRecursive(backupFuncPath, targetFuncPath);
61
61
  }
62
62
 
63
- console.log(chalk.gray(` - Linkando com projeto ${targetProject.targetProjectId}...`));
63
+ console.log(chalk.white(` - Linkando com projeto ${targetProject.targetProjectId}...`));
64
64
 
65
65
  // Linkar com o projeto destino
66
66
  try {
@@ -77,7 +77,7 @@ module.exports = async ({ backupPath, targetProject }) => {
77
77
  // Deploy das Edge Functions
78
78
  let successCount = 0;
79
79
  for (const funcName of functions) {
80
- console.log(chalk.gray(` - Deployando ${funcName}...`));
80
+ console.log(chalk.white(` - Deployando ${funcName}...`));
81
81
 
82
82
  try {
83
83
  execSync(`supabase functions deploy ${funcName}`, {
@@ -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 {
@@ -25,11 +25,11 @@ module.exports = async ({ backupPath, targetProject }) => {
25
25
 
26
26
  if (authSettings.settings?.auth_url_config) {
27
27
  Object.entries(authSettings.settings.auth_url_config).forEach(([key, value]) => {
28
- console.log(chalk.gray(` - ${key}: ${value}`));
28
+ console.log(chalk.white(` - ${key}: ${value}`));
29
29
  });
30
30
  } else if (authSettings.auth_url_config) {
31
31
  Object.entries(authSettings.auth_url_config).forEach(([key, value]) => {
32
- console.log(chalk.gray(` - ${key}: ${value}`));
32
+ console.log(chalk.white(` - ${key}: ${value}`));
33
33
  });
34
34
  }
35
35
 
@@ -26,23 +26,23 @@ module.exports = async ({ backupPath }) => {
26
26
  const buckets = manifest?.components?.storage?.buckets || [];
27
27
 
28
28
  if (buckets.length === 0) {
29
- console.log(chalk.gray(' ℹ️ Nenhum bucket para restaurar'));
29
+ console.log(chalk.white(' ℹ️ Nenhum bucket para restaurar'));
30
30
  return { success: false, buckets_count: 0 };
31
31
  }
32
32
 
33
33
  console.log(chalk.green(`\n ✅ ${buckets.length} bucket(s) encontrado(s) no backup`));
34
34
  buckets.forEach(bucket => {
35
- console.log(chalk.gray(` - ${bucket.name} (${bucket.public ? 'público' : 'privado'})`));
35
+ console.log(chalk.white(` - ${bucket.name} (${bucket.public ? 'público' : 'privado'})`));
36
36
  });
37
37
 
38
38
  const colabUrl = 'https://colab.research.google.com/github/PLyn/supabase-storage-migrate/blob/main/Supabase_Storage_migration.ipynb';
39
39
 
40
40
  console.log(chalk.yellow('\n ⚠️ Migração de objetos de Storage requer processo manual'));
41
41
  console.log(chalk.cyan(` ℹ️ Use o script do Google Colab: ${colabUrl}`));
42
- console.log(chalk.gray('\n 📋 Instruções:'));
43
- console.log(chalk.gray(' 1. Execute o script no Google Colab'));
44
- console.log(chalk.gray(' 2. Configure as credenciais dos projetos (origem e destino)'));
45
- console.log(chalk.gray(' 3. Execute a migração'));
42
+ console.log(chalk.white('\n 📋 Instruções:'));
43
+ console.log(chalk.white(' 1. Execute o script no Google Colab'));
44
+ console.log(chalk.white(' 2. Configure as credenciais dos projetos (origem e destino)'));
45
+ console.log(chalk.white(' 3. Execute a migração'));
46
46
 
47
47
  await inquirer.prompt([{
48
48
  type: 'input',
@@ -22,11 +22,11 @@ module.exports = async ({ backupPath, targetProject }) => {
22
22
  const extensions = dbSettings.extensions || [];
23
23
 
24
24
  if (extensions.length > 0) {
25
- console.log(chalk.gray(` - Habilitando ${extensions.length} extension(s)...`));
25
+ console.log(chalk.white(` - Habilitando ${extensions.length} extension(s)...`));
26
26
 
27
27
  for (const ext of extensions) {
28
28
  const extName = typeof ext === 'string' ? ext : ext.name;
29
- console.log(chalk.gray(` - ${extName}`));
29
+ console.log(chalk.white(` - ${extName}`));
30
30
 
31
31
  const sqlCommand = `CREATE EXTENSION IF NOT EXISTS ${extName};`;
32
32
 
@@ -25,9 +25,9 @@ module.exports = async ({ backupPath, targetProject }) => {
25
25
 
26
26
  if (realtimeSettings.realtime_settings?.settings) {
27
27
  Object.values(realtimeSettings.realtime_settings.settings).forEach((setting) => {
28
- console.log(chalk.gray(` - ${setting.label}: ${setting.value}`));
28
+ console.log(chalk.white(` - ${setting.label}: ${setting.value}`));
29
29
  if (setting.description) {
30
- console.log(chalk.gray(` ${setting.description}`));
30
+ console.log(chalk.white(` ${setting.description}`));
31
31
  }
32
32
  });
33
33
  }
@@ -28,7 +28,7 @@ async function ensureCleanLink(projectRef, accessToken, dbPassword) {
28
28
  const tempDir = path.join(process.cwd(), 'supabase', '.temp');
29
29
 
30
30
  // Remover supabase/.temp completamente
31
- console.log(chalk.gray(` - Zerando vínculo e linkando projeto: ${projectRef}...`));
31
+ console.log(chalk.white(` - Zerando vínculo e linkando projeto: ${projectRef}...`));
32
32
 
33
33
  try {
34
34
  await fs.rm(tempDir, { recursive: true, force: true });
@@ -66,7 +66,7 @@ async function ensureCleanLink(projectRef, accessToken, dbPassword) {
66
66
  );
67
67
  }
68
68
 
69
- console.log(chalk.gray(` - Validação: linked-ref = ${linkedRefTrimmed} (esperado = ${projectRef})`));
69
+ console.log(chalk.white(` - Validação: linked-ref = ${linkedRefTrimmed} (esperado = ${projectRef})`));
70
70
  } catch (error) {
71
71
  if (error.message.includes('Validação falhou')) {
72
72
  throw error;