smoonb 0.0.6 → 0.0.8
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/.smoonbrc +7 -6
- package/.smoonbrc.example +2 -1
- package/README.md +164 -164
- package/backups/backup-2025-10-17T19-52-20-211Z/auth-config.json +7 -0
- package/backups/backup-2025-10-17T19-52-20-211Z/backup-manifest.json +19 -0
- package/backups/backup-2025-10-17T19-52-20-211Z/database-2025-10-17T19-52-20-215Z.dump +0 -0
- package/backups/backup-2025-10-17T19-52-20-211Z/functions/README.md +4 -0
- package/backups/backup-2025-10-17T19-52-20-211Z/realtime-config.json +7 -0
- package/backups/backup-2025-10-17T19-52-20-211Z/storage/storage-config.json +6 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/auth-config.json +7 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/backup-manifest.json +19 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/database-2025-10-17T20-38-13-194Z.dump +0 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/functions/README.md +4 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/realtime-config.json +7 -0
- package/backups/backup-2025-10-17T20-38-13-188Z/storage/storage-config.json +6 -0
- package/bin/smoonb.js +16 -32
- package/package.json +1 -1
- package/src/commands/backup.js +140 -239
- package/src/commands/check.js +209 -349
- package/src/commands/config.js +78 -77
- package/src/commands/functions.js +123 -349
- package/src/commands/restore.js +122 -294
- package/src/index.js +12 -21
- package/src/services/introspect.js +299 -0
- package/src/utils/cli.js +87 -0
- package/src/utils/config.js +140 -0
- package/src/utils/fsx.js +110 -0
- package/src/utils/hash.js +40 -0
- package/src/utils/supabase.js +447 -387
- package/src/commands/secrets.js +0 -361
- /package/{backup → backups}/backup-2025-10-17T19-18-58-539Z/auth-config.json +0 -0
- /package/{backup → backups}/backup-2025-10-17T19-18-58-539Z/backup-manifest.json +0 -0
- /package/{backup → backups}/backup-2025-10-17T19-18-58-539Z/functions/README.md +0 -0
- /package/{backup → backups}/backup-2025-10-17T19-18-58-539Z/realtime-config.json +0 -0
- /package/{backup → backups}/backup-2025-10-17T19-18-58-539Z/storage/storage-config.json +0 -0
package/src/commands/check.js
CHANGED
|
@@ -1,412 +1,272 @@
|
|
|
1
|
-
|
|
2
|
-
* Comando de checklist pós-restore
|
|
3
|
-
* Verificação de integridade completa
|
|
4
|
-
*/
|
|
5
|
-
|
|
1
|
+
const { Command } = require('commander');
|
|
6
2
|
const chalk = require('chalk');
|
|
7
|
-
const { execSync } = require('child_process');
|
|
8
|
-
const fs = require('fs');
|
|
9
3
|
const path = require('path');
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
async function checkCommand(options) {
|
|
17
|
-
console.log(chalk.red.bold('🚀 smoonb - EXPERIMENTAL VERSION'));
|
|
18
|
-
console.log(chalk.red.bold('⚠️ VERSÃO EXPERIMENTAL - NUNCA TESTADA EM PRODUÇÃO!'));
|
|
19
|
-
console.log(chalk.red.bold('🚨 USE POR SUA CONTA E RISCO - Pode causar perda de dados!'));
|
|
20
|
-
console.log(chalk.red.bold('❌ NÃO NOS RESPONSABILIZAMOS por qualquer perda de dados!\n'));
|
|
21
|
-
|
|
22
|
-
console.log(chalk.cyan.bold('🔍 Checklist pós-restore - Verificação de integridade...\n'));
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const { ensureBin, runCommand } = require('../utils/cli');
|
|
6
|
+
const { readConfig, validateFor, writeJson } = require('../utils/config');
|
|
7
|
+
const { IntrospectionService } = require('../services/introspect');
|
|
8
|
+
const { showBetaBanner } = require('../index');
|
|
23
9
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
const checkCommand = new Command('check')
|
|
11
|
+
.description('Verificar integridade do projeto Supabase após restauração')
|
|
12
|
+
.option('-o, --output <file>', 'Arquivo de saída do relatório', 'check-report.json')
|
|
13
|
+
.action(async (options) => {
|
|
14
|
+
showBetaBanner();
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
try {
|
|
17
|
+
// Verificar se psql está disponível
|
|
18
|
+
const psqlPath = await ensureBin('psql');
|
|
19
|
+
if (!psqlPath) {
|
|
20
|
+
console.error(chalk.red('❌ psql não encontrado'));
|
|
21
|
+
console.log(chalk.yellow('💡 Instale PostgreSQL:'));
|
|
22
|
+
console.log(chalk.yellow(' https://www.postgresql.org/download/'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Carregar configuração
|
|
27
|
+
const config = await readConfig();
|
|
28
|
+
validateFor(config, 'backup'); // Usar mesma validação do backup
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
const databaseUrl = config.supabase.databaseUrl;
|
|
31
|
+
if (!databaseUrl) {
|
|
32
|
+
console.error(chalk.red('❌ databaseUrl não configurada'));
|
|
33
|
+
console.log(chalk.yellow('💡 Configure databaseUrl no .smoonbrc'));
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
const results = await runPostRestoreChecks(projectId, options.verbose);
|
|
37
|
+
console.log(chalk.blue(`🔍 Verificando integridade do projeto: ${config.supabase.projectId}`));
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
// Executar verificações
|
|
40
|
+
const report = await performChecks(config, databaseUrl);
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
}
|
|
42
|
+
// Salvar relatório
|
|
43
|
+
const reportPath = path.resolve(options.output);
|
|
44
|
+
await writeJson(reportPath, report);
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*/
|
|
57
|
-
async function runPostRestoreChecks(projectId, verbose = false) {
|
|
58
|
-
const checks = [
|
|
59
|
-
{ name: 'Database Connection', category: 'database', status: 'pending', details: [] },
|
|
60
|
-
{ name: 'Database Schema', category: 'database', status: 'pending', details: [] },
|
|
61
|
-
{ name: 'Database Extensions', category: 'database', status: 'pending', details: [] },
|
|
62
|
-
{ name: 'Edge Functions', category: 'functions', status: 'pending', details: [] },
|
|
63
|
-
{ name: 'Auth Providers', category: 'auth', status: 'pending', details: [] },
|
|
64
|
-
{ name: 'Auth Policies', category: 'auth', status: 'pending', details: [] },
|
|
65
|
-
{ name: 'Storage Buckets', category: 'storage', status: 'pending', details: [] },
|
|
66
|
-
{ name: 'Storage Objects', category: 'storage', status: 'pending', details: [] },
|
|
67
|
-
{ name: 'Realtime Settings', category: 'realtime', status: 'pending', details: [] },
|
|
68
|
-
{ name: 'API Endpoints', category: 'api', status: 'pending', details: [] }
|
|
69
|
-
];
|
|
46
|
+
// Mostrar resumo
|
|
47
|
+
showCheckSummary(report);
|
|
70
48
|
|
|
71
|
-
|
|
49
|
+
console.log(chalk.green('\n🎉 Verificação concluída!'));
|
|
50
|
+
console.log(chalk.blue(`📋 Relatório salvo em: ${reportPath}`));
|
|
72
51
|
|
|
73
|
-
// Executar verificações por categoria
|
|
74
|
-
for (const check of checks) {
|
|
75
|
-
try {
|
|
76
|
-
await performCheck(check, projectId, verbose);
|
|
77
52
|
} catch (error) {
|
|
78
|
-
|
|
79
|
-
|
|
53
|
+
console.error(chalk.red(`❌ Erro na verificação: ${error.message}`));
|
|
54
|
+
process.exit(1);
|
|
80
55
|
}
|
|
81
|
-
}
|
|
56
|
+
});
|
|
82
57
|
|
|
83
|
-
|
|
84
|
-
|
|
58
|
+
// Executar todas as verificações
|
|
59
|
+
async function performChecks(config, databaseUrl) {
|
|
60
|
+
const report = {
|
|
61
|
+
timestamp: new Date().toISOString(),
|
|
62
|
+
project_id: config.supabase.projectId,
|
|
63
|
+
checks: {}
|
|
64
|
+
};
|
|
85
65
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
async function performCheck(check, projectId, verbose) {
|
|
90
|
-
if (verbose) {
|
|
91
|
-
console.log(chalk.gray(` - Verificando ${check.name}...`));
|
|
92
|
-
}
|
|
66
|
+
// 1. Verificar conexão com database
|
|
67
|
+
console.log(chalk.blue('\n🔌 1/6 - Verificando conexão com database...'));
|
|
68
|
+
report.checks.database_connection = await checkDatabaseConnection(databaseUrl);
|
|
93
69
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
break;
|
|
116
|
-
case 'Storage Objects':
|
|
117
|
-
await checkStorageObjects(check, projectId, verbose);
|
|
118
|
-
break;
|
|
119
|
-
case 'Realtime Settings':
|
|
120
|
-
await checkRealtimeSettings(check, projectId, verbose);
|
|
121
|
-
break;
|
|
122
|
-
case 'API Endpoints':
|
|
123
|
-
await checkAPIEndpoints(check, projectId, verbose);
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
70
|
+
// 2. Verificar extensões
|
|
71
|
+
console.log(chalk.blue('\n🔧 2/6 - Verificando extensões...'));
|
|
72
|
+
report.checks.extensions = await checkExtensions(databaseUrl);
|
|
73
|
+
|
|
74
|
+
// 3. Verificar tabelas
|
|
75
|
+
console.log(chalk.blue('\n📊 3/6 - Verificando tabelas...'));
|
|
76
|
+
report.checks.tables = await checkTables(databaseUrl);
|
|
77
|
+
|
|
78
|
+
// 4. Verificar políticas RLS
|
|
79
|
+
console.log(chalk.blue('\n🔒 4/6 - Verificando políticas RLS...'));
|
|
80
|
+
report.checks.rls_policies = await checkRLSPolicies(databaseUrl);
|
|
81
|
+
|
|
82
|
+
// 5. Verificar Realtime
|
|
83
|
+
console.log(chalk.blue('\n🔄 5/6 - Verificando Realtime...'));
|
|
84
|
+
report.checks.realtime = await checkRealtime(databaseUrl);
|
|
85
|
+
|
|
86
|
+
// 6. Verificar Storage
|
|
87
|
+
console.log(chalk.blue('\n📦 6/6 - Verificando Storage...'));
|
|
88
|
+
report.checks.storage = await checkStorage(config);
|
|
89
|
+
|
|
90
|
+
return report;
|
|
126
91
|
}
|
|
127
92
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
async function checkDatabaseConnection(check, projectId, verbose) {
|
|
93
|
+
// Verificar conexão com database
|
|
94
|
+
async function checkDatabaseConnection(databaseUrl) {
|
|
132
95
|
try {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const testCmd = `psql "${dbUrl}" -c "SELECT 1;"`;
|
|
137
|
-
execSync(testCmd, { stdio: 'pipe' });
|
|
96
|
+
const { stdout } = await runCommand(
|
|
97
|
+
`psql "${databaseUrl}" -t -c "SELECT 1 as test_connection;"`
|
|
98
|
+
);
|
|
138
99
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
console.log(chalk.gray(' ✅ Conexão com database OK'));
|
|
100
|
+
if (stdout.trim() === '1') {
|
|
101
|
+
return { status: 'ok', message: 'Conexão estabelecida com sucesso' };
|
|
102
|
+
} else {
|
|
103
|
+
return { status: 'error', message: 'Resposta inesperada da database' };
|
|
144
104
|
}
|
|
145
105
|
} catch (error) {
|
|
146
|
-
|
|
147
|
-
check.details.push('Conexão falhou (credenciais não configuradas)');
|
|
148
|
-
|
|
149
|
-
if (verbose) {
|
|
150
|
-
console.log(chalk.gray(' ⚠️ Conexão com database falhou'));
|
|
151
|
-
}
|
|
106
|
+
return { status: 'error', message: `Falha na conexão: ${error.message}` };
|
|
152
107
|
}
|
|
153
108
|
}
|
|
154
109
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
*/
|
|
158
|
-
async function checkDatabaseSchema(check, projectId, verbose) {
|
|
110
|
+
// Verificar extensões
|
|
111
|
+
async function checkExtensions(databaseUrl) {
|
|
159
112
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
113
|
+
const query = `
|
|
114
|
+
SELECT extname, extversion
|
|
115
|
+
FROM pg_extension
|
|
116
|
+
ORDER BY extname;
|
|
117
|
+
`;
|
|
165
118
|
|
|
166
|
-
const
|
|
167
|
-
|
|
119
|
+
const { stdout } = await runCommand(
|
|
120
|
+
`psql "${databaseUrl}" -t -c "${query}"`
|
|
121
|
+
);
|
|
168
122
|
|
|
169
|
-
|
|
170
|
-
|
|
123
|
+
const extensions = stdout.trim().split('\n')
|
|
124
|
+
.filter(line => line.trim())
|
|
125
|
+
.map(line => {
|
|
126
|
+
const [name, version] = line.trim().split('|');
|
|
127
|
+
return { name: name?.trim(), version: version?.trim() };
|
|
128
|
+
});
|
|
171
129
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
130
|
+
return {
|
|
131
|
+
status: 'ok',
|
|
132
|
+
message: `${extensions.length} extensões encontradas`,
|
|
133
|
+
data: extensions
|
|
134
|
+
};
|
|
175
135
|
} catch (error) {
|
|
176
|
-
|
|
177
|
-
check.details.push('Não foi possível verificar schema (credenciais não configuradas)');
|
|
178
|
-
|
|
179
|
-
if (verbose) {
|
|
180
|
-
console.log(chalk.gray(' ⚠️ Verificação de schema falhou'));
|
|
181
|
-
}
|
|
136
|
+
return { status: 'error', message: `Erro ao verificar extensões: ${error.message}` };
|
|
182
137
|
}
|
|
183
138
|
}
|
|
184
139
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
*/
|
|
188
|
-
async function checkDatabaseExtensions(check, projectId, verbose) {
|
|
140
|
+
// Verificar tabelas
|
|
141
|
+
async function checkTables(databaseUrl) {
|
|
189
142
|
try {
|
|
190
|
-
const
|
|
143
|
+
const query = `
|
|
144
|
+
SELECT schemaname, tablename, tableowner
|
|
145
|
+
FROM pg_tables
|
|
146
|
+
WHERE schemaname IN ('public', 'auth', 'storage')
|
|
147
|
+
ORDER BY schemaname, tablename;
|
|
148
|
+
`;
|
|
191
149
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
150
|
+
const { stdout } = await runCommand(
|
|
151
|
+
`psql "${databaseUrl}" -t -c "${query}"`
|
|
152
|
+
);
|
|
195
153
|
|
|
196
|
-
const
|
|
197
|
-
|
|
154
|
+
const tables = stdout.trim().split('\n')
|
|
155
|
+
.filter(line => line.trim())
|
|
156
|
+
.map(line => {
|
|
157
|
+
const [schema, table, owner] = line.trim().split('|');
|
|
158
|
+
return {
|
|
159
|
+
schema: schema?.trim(),
|
|
160
|
+
table: table?.trim(),
|
|
161
|
+
owner: owner?.trim()
|
|
162
|
+
};
|
|
163
|
+
});
|
|
198
164
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
165
|
+
return {
|
|
166
|
+
status: 'ok',
|
|
167
|
+
message: `${tables.length} tabelas encontradas`,
|
|
168
|
+
data: tables
|
|
169
|
+
};
|
|
205
170
|
} catch (error) {
|
|
206
|
-
|
|
207
|
-
check.details.push('Não foi possível verificar extensões (credenciais não configuradas)');
|
|
208
|
-
|
|
209
|
-
if (verbose) {
|
|
210
|
-
console.log(chalk.gray(' ⚠️ Verificação de extensões falhou'));
|
|
211
|
-
}
|
|
171
|
+
return { status: 'error', message: `Erro ao verificar tabelas: ${error.message}` };
|
|
212
172
|
}
|
|
213
173
|
}
|
|
214
174
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*/
|
|
218
|
-
async function checkEdgeFunctions(check, projectId, verbose) {
|
|
175
|
+
// Verificar políticas RLS
|
|
176
|
+
async function checkRLSPolicies(databaseUrl) {
|
|
219
177
|
try {
|
|
220
|
-
|
|
221
|
-
|
|
178
|
+
const query = `
|
|
179
|
+
SELECT COUNT(*) as policy_count
|
|
180
|
+
FROM pg_policies;
|
|
181
|
+
`;
|
|
222
182
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
183
|
+
const { stdout } = await runCommand(
|
|
184
|
+
`psql "${databaseUrl}" -t -c "${query}"`
|
|
185
|
+
);
|
|
226
186
|
|
|
227
|
-
|
|
228
|
-
const lines = output.split('\n').filter(line => line.trim());
|
|
229
|
-
const functionCount = lines.length;
|
|
230
|
-
|
|
231
|
-
check.status = 'ok';
|
|
232
|
-
check.details.push(`${functionCount} Edge Functions encontradas`);
|
|
233
|
-
|
|
234
|
-
if (verbose) {
|
|
235
|
-
console.log(chalk.gray(` ✅ Edge Functions OK (${functionCount} encontradas)`));
|
|
236
|
-
}
|
|
237
|
-
} else {
|
|
238
|
-
check.status = 'warning';
|
|
239
|
-
check.details.push('Nenhuma Edge Function encontrada');
|
|
240
|
-
|
|
241
|
-
if (verbose) {
|
|
242
|
-
console.log(chalk.gray(' ⚠️ Nenhuma Edge Function encontrada'));
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
} catch (error) {
|
|
246
|
-
check.status = 'warning';
|
|
247
|
-
check.details.push('Supabase CLI não encontrado ou projeto não configurado');
|
|
187
|
+
const policyCount = parseInt(stdout.trim());
|
|
248
188
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* Verificar Auth Providers
|
|
257
|
-
*/
|
|
258
|
-
async function checkAuthProviders(check, projectId, verbose) {
|
|
259
|
-
// TODO: Implementar verificação real via Supabase API
|
|
260
|
-
check.status = 'warning';
|
|
261
|
-
check.details.push('Verificação de Auth Providers em desenvolvimento');
|
|
262
|
-
|
|
263
|
-
if (verbose) {
|
|
264
|
-
console.log(chalk.gray(' ⚠️ Verificação de Auth Providers em desenvolvimento'));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Verificar Auth Policies
|
|
270
|
-
*/
|
|
271
|
-
async function checkAuthPolicies(check, projectId, verbose) {
|
|
272
|
-
// TODO: Implementar verificação real via Supabase API
|
|
273
|
-
check.status = 'warning';
|
|
274
|
-
check.details.push('Verificação de Auth Policies em desenvolvimento');
|
|
275
|
-
|
|
276
|
-
if (verbose) {
|
|
277
|
-
console.log(chalk.gray(' ⚠️ Verificação de Auth Policies em desenvolvimento'));
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Verificar Storage Buckets
|
|
283
|
-
*/
|
|
284
|
-
async function checkStorageBuckets(check, projectId, verbose) {
|
|
285
|
-
// TODO: Implementar verificação real via Supabase API
|
|
286
|
-
check.status = 'warning';
|
|
287
|
-
check.details.push('Verificação de Storage Buckets em desenvolvimento');
|
|
288
|
-
|
|
289
|
-
if (verbose) {
|
|
290
|
-
console.log(chalk.gray(' ⚠️ Verificação de Storage Buckets em desenvolvimento'));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Verificar Storage Objects
|
|
296
|
-
*/
|
|
297
|
-
async function checkStorageObjects(check, projectId, verbose) {
|
|
298
|
-
// TODO: Implementar verificação real via Supabase API
|
|
299
|
-
check.status = 'warning';
|
|
300
|
-
check.details.push('Verificação de Storage Objects em desenvolvimento');
|
|
301
|
-
|
|
302
|
-
if (verbose) {
|
|
303
|
-
console.log(chalk.gray(' ⚠️ Verificação de Storage Objects em desenvolvimento'));
|
|
189
|
+
return {
|
|
190
|
+
status: 'ok',
|
|
191
|
+
message: `${policyCount} políticas RLS encontradas`,
|
|
192
|
+
data: { policy_count: policyCount }
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return { status: 'error', message: `Erro ao verificar políticas RLS: ${error.message}` };
|
|
304
196
|
}
|
|
305
197
|
}
|
|
306
198
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
199
|
+
// Verificar Realtime
|
|
200
|
+
async function checkRealtime(databaseUrl) {
|
|
201
|
+
try {
|
|
202
|
+
const query = `
|
|
203
|
+
SELECT pubname
|
|
204
|
+
FROM pg_publication
|
|
205
|
+
ORDER BY pubname;
|
|
206
|
+
`;
|
|
207
|
+
|
|
208
|
+
const { stdout } = await runCommand(
|
|
209
|
+
`psql "${databaseUrl}" -t -c "${query}"`
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
const publications = stdout.trim().split('\n')
|
|
213
|
+
.filter(line => line.trim())
|
|
214
|
+
.map(line => line.trim());
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
status: 'ok',
|
|
218
|
+
message: `${publications.length} publicações Realtime encontradas`,
|
|
219
|
+
data: { publications }
|
|
220
|
+
};
|
|
221
|
+
} catch (error) {
|
|
222
|
+
return { status: 'error', message: `Erro ao verificar Realtime: ${error.message}` };
|
|
317
223
|
}
|
|
318
224
|
}
|
|
319
225
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
*/
|
|
323
|
-
async function checkAPIEndpoints(check, projectId, verbose) {
|
|
226
|
+
// Verificar Storage
|
|
227
|
+
async function checkStorage(config) {
|
|
324
228
|
try {
|
|
325
|
-
const
|
|
229
|
+
const introspection = new IntrospectionService(config);
|
|
230
|
+
const storageInventory = await introspection.getStorageInventory();
|
|
326
231
|
|
|
327
|
-
|
|
328
|
-
const
|
|
232
|
+
const bucketCount = storageInventory.buckets?.length || 0;
|
|
233
|
+
const totalObjects = storageInventory.buckets?.reduce(
|
|
234
|
+
(total, bucket) => total + (bucket.objects?.length || 0), 0
|
|
235
|
+
) || 0;
|
|
329
236
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
console.log(chalk.gray(' ✅ API endpoints OK'));
|
|
336
|
-
}
|
|
237
|
+
return {
|
|
238
|
+
status: 'ok',
|
|
239
|
+
message: `${bucketCount} buckets e ${totalObjects} objetos encontrados`,
|
|
240
|
+
data: storageInventory
|
|
241
|
+
};
|
|
337
242
|
} catch (error) {
|
|
338
|
-
|
|
339
|
-
check.details.push('Não foi possível verificar API endpoints');
|
|
340
|
-
|
|
341
|
-
if (verbose) {
|
|
342
|
-
console.log(chalk.gray(' ⚠️ Verificação de API endpoints falhou'));
|
|
343
|
-
}
|
|
243
|
+
return { status: 'error', message: `Erro ao verificar Storage: ${error.message}` };
|
|
344
244
|
}
|
|
345
245
|
}
|
|
346
246
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
results.forEach(check => {
|
|
356
|
-
if (!categories[check.category]) {
|
|
357
|
-
categories[check.category] = [];
|
|
358
|
-
}
|
|
359
|
-
categories[check.category].push(check);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
// Mostrar por categoria
|
|
363
|
-
Object.entries(categories).forEach(([category, checks]) => {
|
|
364
|
-
const categoryName = category.charAt(0).toUpperCase() + category.slice(1);
|
|
365
|
-
console.log(chalk.cyan.bold(`📁 ${categoryName}:`));
|
|
247
|
+
// Mostrar resumo das verificações
|
|
248
|
+
function showCheckSummary(report) {
|
|
249
|
+
console.log(chalk.blue('\n📋 RESUMO DAS VERIFICAÇÕES:'));
|
|
250
|
+
console.log(chalk.blue('═'.repeat(50)));
|
|
251
|
+
|
|
252
|
+
for (const [checkName, result] of Object.entries(report.checks)) {
|
|
253
|
+
const icon = result.status === 'ok' ? '✅' : '❌';
|
|
254
|
+
const color = result.status === 'ok' ? chalk.green : chalk.red;
|
|
366
255
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
console.log();
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
// Estatísticas gerais
|
|
385
|
-
const totalChecks = results.length;
|
|
386
|
-
const okChecks = results.filter(c => c.status === 'ok').length;
|
|
387
|
-
const warningChecks = results.filter(c => c.status === 'warning').length;
|
|
388
|
-
const errorChecks = results.filter(c => c.status === 'error').length;
|
|
389
|
-
|
|
390
|
-
console.log(chalk.blue.bold('📈 Estatísticas:'));
|
|
391
|
-
console.log(chalk.green(`✅ OK: ${okChecks}/${totalChecks}`));
|
|
392
|
-
console.log(chalk.yellow(`⚠️ Avisos: ${warningChecks}/${totalChecks}`));
|
|
393
|
-
console.log(chalk.red(`❌ Erros: ${errorChecks}/${totalChecks}`));
|
|
394
|
-
|
|
395
|
-
// Status geral
|
|
396
|
-
if (errorChecks === 0 && warningChecks === 0) {
|
|
397
|
-
console.log(chalk.green.bold('\n🎉 Todas as verificações passaram com sucesso!'));
|
|
398
|
-
} else if (errorChecks === 0) {
|
|
399
|
-
console.log(chalk.yellow.bold('\n⚠️ Verificações concluídas com avisos'));
|
|
400
|
-
console.log(chalk.gray(' - Projeto funcional, mas algumas verificações precisam de atenção'));
|
|
256
|
+
console.log(`${icon} ${color(checkName.replace(/_/g, ' ').toUpperCase())}: ${result.message}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const okCount = Object.values(report.checks).filter(c => c.status === 'ok').length;
|
|
260
|
+
const totalCount = Object.keys(report.checks).length;
|
|
261
|
+
|
|
262
|
+
console.log(chalk.blue('═'.repeat(50)));
|
|
263
|
+
console.log(chalk.blue(`📊 Resultado: ${okCount}/${totalCount} verificações passaram`));
|
|
264
|
+
|
|
265
|
+
if (okCount === totalCount) {
|
|
266
|
+
console.log(chalk.green('🎉 Todas as verificações passaram!'));
|
|
401
267
|
} else {
|
|
402
|
-
console.log(chalk.
|
|
403
|
-
console.log(chalk.gray(' - Alguns componentes podem não estar funcionando corretamente'));
|
|
268
|
+
console.log(chalk.yellow('⚠️ Algumas verificações falharam. Verifique o relatório completo.'));
|
|
404
269
|
}
|
|
405
|
-
|
|
406
|
-
console.log(chalk.yellow('\n💡 Dicas:'));
|
|
407
|
-
console.log(chalk.gray(' - Configure credenciais: smoonb config --init'));
|
|
408
|
-
console.log(chalk.gray(' - Instale Supabase CLI: npm install -g supabase'));
|
|
409
|
-
console.log(chalk.gray(' - Execute verificações detalhadas: smoonb check --verbose'));
|
|
410
270
|
}
|
|
411
271
|
|
|
412
|
-
module.exports = checkCommand;
|
|
272
|
+
module.exports = checkCommand;
|