smoonb 0.0.6 → 0.0.7
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 +30 -25
- 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 +10 -10
- package/package.json +1 -1
- package/src/commands/backup.js +16 -6
- package/src/commands/config.js +78 -77
- package/src/utils/supabase.js +447 -387
- /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/utils/supabase.js
CHANGED
|
@@ -1,387 +1,447 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilitários para conexão e operações com Supabase
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { createClient } = require('@supabase/supabase-js');
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const os = require('os');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
throw
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
//
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Obter configurações de
|
|
349
|
-
*/
|
|
350
|
-
async function
|
|
351
|
-
try {
|
|
352
|
-
const client = getSupabaseClient();
|
|
353
|
-
|
|
354
|
-
// TODO: Implementar busca real de configurações de
|
|
355
|
-
// Por enquanto, retornar estrutura básica
|
|
356
|
-
return {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
settings: {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
} catch (error) {
|
|
365
|
-
throw new Error(`Erro ao obter configurações de
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Utilitários para conexão e operações com Supabase
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { createClient } = require('@supabase/supabase-js');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Cliente Supabase configurado
|
|
13
|
+
*/
|
|
14
|
+
let supabaseClient = null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Encontrar caminho do pg_dump no Windows
|
|
18
|
+
*/
|
|
19
|
+
function findPgDumpPath() {
|
|
20
|
+
// Tentar configuração personalizada primeiro
|
|
21
|
+
const config = loadConfig();
|
|
22
|
+
if (config?.backup?.pgDumpPath && fs.existsSync(config.backup.pgDumpPath)) {
|
|
23
|
+
return config.backup.pgDumpPath;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Detecção automática no Windows
|
|
27
|
+
const possiblePaths = [
|
|
28
|
+
'C:\\Program Files\\PostgreSQL\\17\\bin\\pg_dump.exe',
|
|
29
|
+
'C:\\Program Files\\PostgreSQL\\16\\bin\\pg_dump.exe',
|
|
30
|
+
'C:\\Program Files\\PostgreSQL\\15\\bin\\pg_dump.exe',
|
|
31
|
+
'C:\\Program Files\\PostgreSQL\\14\\bin\\pg_dump.exe',
|
|
32
|
+
'C:\\Program Files\\PostgreSQL\\13\\bin\\pg_dump.exe',
|
|
33
|
+
'C:\\Program Files\\PostgreSQL\\12\\bin\\pg_dump.exe',
|
|
34
|
+
'pg_dump' // Fallback para PATH
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
for (const pgPath of possiblePaths) {
|
|
38
|
+
try {
|
|
39
|
+
if (pgPath === 'pg_dump') {
|
|
40
|
+
// Testar se está no PATH
|
|
41
|
+
execSync('pg_dump --version', { stdio: 'pipe' });
|
|
42
|
+
return pgPath;
|
|
43
|
+
} else if (fs.existsSync(pgPath)) {
|
|
44
|
+
return pgPath;
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
// Continuar para o próximo caminho
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw new Error('pg_dump não encontrado. Instale o PostgreSQL ou configure pgDumpPath no .smoonbrc');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Inicializar cliente Supabase
|
|
57
|
+
*/
|
|
58
|
+
function initSupabaseClient() {
|
|
59
|
+
try {
|
|
60
|
+
const supabaseUrl = process.env.SUPABASE_URL;
|
|
61
|
+
const supabaseKey = process.env.SUPABASE_ANON_KEY || process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
62
|
+
|
|
63
|
+
if (!supabaseUrl || !supabaseKey) {
|
|
64
|
+
throw new Error('SUPABASE_URL e SUPABASE_ANON_KEY são obrigatórios');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
supabaseClient = createClient(supabaseUrl, supabaseKey);
|
|
68
|
+
return supabaseClient;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
throw new Error(`Erro ao inicializar cliente Supabase: ${error.message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Obter cliente Supabase (inicializa se necessário)
|
|
76
|
+
*/
|
|
77
|
+
function getSupabaseClient() {
|
|
78
|
+
if (!supabaseClient) {
|
|
79
|
+
return initSupabaseClient();
|
|
80
|
+
}
|
|
81
|
+
return supabaseClient;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Carregar configuração do arquivo .smoonbrc
|
|
86
|
+
*/
|
|
87
|
+
function loadConfig() {
|
|
88
|
+
// Primeiro tentar no diretório do projeto atual
|
|
89
|
+
const projectConfigPath = path.join(process.cwd(), '.smoonbrc');
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
if (fs.existsSync(projectConfigPath)) {
|
|
93
|
+
const configContent = fs.readFileSync(projectConfigPath, 'utf8');
|
|
94
|
+
return JSON.parse(configContent);
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.warn('Erro ao carregar configuração do projeto:', error.message);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Fallback: tentar no diretório home
|
|
101
|
+
const homeConfigPath = path.join(os.homedir(), '.smoonbrc');
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
if (fs.existsSync(homeConfigPath)) {
|
|
105
|
+
const configContent = fs.readFileSync(homeConfigPath, 'utf8');
|
|
106
|
+
return JSON.parse(configContent);
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn('Erro ao carregar configuração do home:', error.message);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Salvar configuração no arquivo .smoonbrc
|
|
117
|
+
*/
|
|
118
|
+
function saveConfig(config) {
|
|
119
|
+
// Salvar no diretório do projeto atual
|
|
120
|
+
const projectConfigPath = path.join(process.cwd(), '.smoonbrc');
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
fs.writeFileSync(projectConfigPath, JSON.stringify(config, null, 2));
|
|
124
|
+
return true;
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('Erro ao salvar configuração:', error.message);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Obter Project ID do Supabase
|
|
133
|
+
*/
|
|
134
|
+
function getProjectId() {
|
|
135
|
+
// Tentar variável de ambiente primeiro
|
|
136
|
+
if (process.env.SUPABASE_PROJECT_ID) {
|
|
137
|
+
return process.env.SUPABASE_PROJECT_ID;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Tentar configuração
|
|
141
|
+
const config = loadConfig();
|
|
142
|
+
if (config?.supabase?.projectId &&
|
|
143
|
+
config.supabase.projectId.trim() !== '' &&
|
|
144
|
+
config.supabase.projectId !== 'your-project-id-here') {
|
|
145
|
+
return config.supabase.projectId;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Obter URL de conexão da database
|
|
153
|
+
*/
|
|
154
|
+
function getDatabaseUrl(projectId = null) {
|
|
155
|
+
// Tentar variável de ambiente primeiro
|
|
156
|
+
if (process.env.DATABASE_URL) {
|
|
157
|
+
return process.env.DATABASE_URL;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Tentar configuração
|
|
161
|
+
const config = loadConfig();
|
|
162
|
+
if (config?.supabase?.databaseUrl &&
|
|
163
|
+
config.supabase.databaseUrl.trim() !== '' &&
|
|
164
|
+
!config.supabase.databaseUrl.includes('your-project') &&
|
|
165
|
+
!config.supabase.databaseUrl.includes('[password]')) {
|
|
166
|
+
return config.supabase.databaseUrl;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Se projectId foi fornecido, usar URL padrão
|
|
170
|
+
if (projectId) {
|
|
171
|
+
return `postgresql://postgres:[password]@db.${projectId}.supabase.co:5432/postgres`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Obter URL do projeto Supabase
|
|
179
|
+
*/
|
|
180
|
+
function getSupabaseUrl(projectId) {
|
|
181
|
+
// Tentar variável de ambiente primeiro
|
|
182
|
+
if (process.env.SUPABASE_URL) {
|
|
183
|
+
return process.env.SUPABASE_URL;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Tentar configuração
|
|
187
|
+
const config = loadConfig();
|
|
188
|
+
if (config?.supabase?.url) {
|
|
189
|
+
return config.supabase.url;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// URL padrão
|
|
193
|
+
return `https://${projectId}.supabase.co`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Obter service key do Supabase
|
|
198
|
+
*/
|
|
199
|
+
function getServiceKey() {
|
|
200
|
+
// Tentar variável de ambiente primeiro
|
|
201
|
+
if (process.env.SUPABASE_SERVICE_ROLE_KEY) {
|
|
202
|
+
return process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Tentar configuração
|
|
206
|
+
const config = loadConfig();
|
|
207
|
+
if (config?.supabase?.serviceKey) {
|
|
208
|
+
return config.supabase.serviceKey;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Obter anon key do Supabase
|
|
216
|
+
*/
|
|
217
|
+
function getAnonKey() {
|
|
218
|
+
// Tentar variável de ambiente primeiro
|
|
219
|
+
if (process.env.SUPABASE_ANON_KEY) {
|
|
220
|
+
return process.env.SUPABASE_ANON_KEY;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Tentar configuração
|
|
224
|
+
const config = loadConfig();
|
|
225
|
+
if (config?.supabase?.anonKey) {
|
|
226
|
+
return config.supabase.anonKey;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Verificar se credenciais estão configuradas
|
|
234
|
+
*/
|
|
235
|
+
function hasCredentials() {
|
|
236
|
+
return !!(getSupabaseUrl() && (getServiceKey() || getAnonKey()));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Testar conexão com Supabase
|
|
241
|
+
*/
|
|
242
|
+
async function testConnection() {
|
|
243
|
+
try {
|
|
244
|
+
const client = getSupabaseClient();
|
|
245
|
+
|
|
246
|
+
// Tentar uma operação simples
|
|
247
|
+
const { data, error } = await client.from('_smoonb_test').select('*').limit(1);
|
|
248
|
+
|
|
249
|
+
if (error && error.code !== 'PGRST116') { // PGRST116 = tabela não existe (esperado)
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return { success: true, message: 'Conexão estabelecida com sucesso' };
|
|
254
|
+
} catch (error) {
|
|
255
|
+
return { success: false, message: error.message };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Obter informações do projeto
|
|
261
|
+
*/
|
|
262
|
+
async function getProjectInfo(projectId) {
|
|
263
|
+
try {
|
|
264
|
+
const client = getSupabaseClient();
|
|
265
|
+
|
|
266
|
+
// TODO: Implementar busca real de informações do projeto
|
|
267
|
+
// Por enquanto, retornar informações básicas
|
|
268
|
+
return {
|
|
269
|
+
id: projectId,
|
|
270
|
+
url: getSupabaseUrl(projectId),
|
|
271
|
+
status: 'active',
|
|
272
|
+
region: 'unknown',
|
|
273
|
+
created_at: new Date().toISOString()
|
|
274
|
+
};
|
|
275
|
+
} catch (error) {
|
|
276
|
+
throw new Error(`Erro ao obter informações do projeto: ${error.message}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Listar tabelas da database
|
|
282
|
+
*/
|
|
283
|
+
async function listTables() {
|
|
284
|
+
try {
|
|
285
|
+
const client = getSupabaseClient();
|
|
286
|
+
|
|
287
|
+
// Usar RPC para listar tabelas
|
|
288
|
+
const { data, error } = await client.rpc('get_tables');
|
|
289
|
+
|
|
290
|
+
if (error) {
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return data || [];
|
|
295
|
+
} catch (error) {
|
|
296
|
+
// Fallback: tentar query direta
|
|
297
|
+
try {
|
|
298
|
+
const { data, error } = await client
|
|
299
|
+
.from('information_schema.tables')
|
|
300
|
+
.select('table_name')
|
|
301
|
+
.eq('table_schema', 'public');
|
|
302
|
+
|
|
303
|
+
if (error) {
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return data?.map(row => row.table_name) || [];
|
|
308
|
+
} catch (fallbackError) {
|
|
309
|
+
throw new Error(`Erro ao listar tabelas: ${fallbackError.message}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Listar extensões instaladas
|
|
316
|
+
*/
|
|
317
|
+
async function listExtensions() {
|
|
318
|
+
try {
|
|
319
|
+
const client = getSupabaseClient();
|
|
320
|
+
|
|
321
|
+
// Usar RPC para listar extensões
|
|
322
|
+
const { data, error } = await client.rpc('get_extensions');
|
|
323
|
+
|
|
324
|
+
if (error) {
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return data || [];
|
|
329
|
+
} catch (error) {
|
|
330
|
+
// Fallback: tentar query direta
|
|
331
|
+
try {
|
|
332
|
+
const { data, error } = await client
|
|
333
|
+
.from('pg_extension')
|
|
334
|
+
.select('extname');
|
|
335
|
+
|
|
336
|
+
if (error) {
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return data?.map(row => row.extname) || [];
|
|
341
|
+
} catch (fallbackError) {
|
|
342
|
+
throw new Error(`Erro ao listar extensões: ${fallbackError.message}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Obter configurações de Auth
|
|
349
|
+
*/
|
|
350
|
+
async function getAuthSettings() {
|
|
351
|
+
try {
|
|
352
|
+
const client = getSupabaseClient();
|
|
353
|
+
|
|
354
|
+
// TODO: Implementar busca real de configurações de Auth
|
|
355
|
+
// Por enquanto, retornar estrutura básica
|
|
356
|
+
return {
|
|
357
|
+
providers: [],
|
|
358
|
+
policies: [],
|
|
359
|
+
settings: {
|
|
360
|
+
enable_signup: true,
|
|
361
|
+
enable_email_confirmations: true
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
} catch (error) {
|
|
365
|
+
throw new Error(`Erro ao obter configurações de Auth: ${error.message}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Obter configurações de Storage
|
|
371
|
+
*/
|
|
372
|
+
async function getStorageSettings() {
|
|
373
|
+
try {
|
|
374
|
+
const client = getSupabaseClient();
|
|
375
|
+
|
|
376
|
+
// Listar buckets
|
|
377
|
+
const { data: buckets, error: bucketsError } = await client.storage.listBuckets();
|
|
378
|
+
|
|
379
|
+
if (bucketsError) {
|
|
380
|
+
throw bucketsError;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Para cada bucket, listar objetos
|
|
384
|
+
const bucketsWithObjects = [];
|
|
385
|
+
for (const bucket of buckets) {
|
|
386
|
+
const { data: objects, error: objectsError } = await client.storage
|
|
387
|
+
.from(bucket.name)
|
|
388
|
+
.list();
|
|
389
|
+
|
|
390
|
+
bucketsWithObjects.push({
|
|
391
|
+
...bucket,
|
|
392
|
+
objects: objects || []
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
buckets: bucketsWithObjects,
|
|
398
|
+
total_buckets: buckets.length,
|
|
399
|
+
total_objects: bucketsWithObjects.reduce((sum, bucket) => sum + bucket.objects.length, 0)
|
|
400
|
+
};
|
|
401
|
+
} catch (error) {
|
|
402
|
+
throw new Error(`Erro ao obter configurações de Storage: ${error.message}`);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Obter configurações de Realtime
|
|
408
|
+
*/
|
|
409
|
+
async function getRealtimeSettings() {
|
|
410
|
+
try {
|
|
411
|
+
const client = getSupabaseClient();
|
|
412
|
+
|
|
413
|
+
// TODO: Implementar busca real de configurações de Realtime
|
|
414
|
+
// Por enquanto, retornar estrutura básica
|
|
415
|
+
return {
|
|
416
|
+
enabled: true,
|
|
417
|
+
channels: [],
|
|
418
|
+
settings: {
|
|
419
|
+
max_channels_per_client: 100,
|
|
420
|
+
max_events_per_second: 100
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
} catch (error) {
|
|
424
|
+
throw new Error(`Erro ao obter configurações de Realtime: ${error.message}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
module.exports = {
|
|
429
|
+
initSupabaseClient,
|
|
430
|
+
getSupabaseClient,
|
|
431
|
+
loadConfig,
|
|
432
|
+
saveConfig,
|
|
433
|
+
getProjectId,
|
|
434
|
+
getDatabaseUrl,
|
|
435
|
+
getSupabaseUrl,
|
|
436
|
+
getServiceKey,
|
|
437
|
+
getAnonKey,
|
|
438
|
+
hasCredentials,
|
|
439
|
+
testConnection,
|
|
440
|
+
getProjectInfo,
|
|
441
|
+
listTables,
|
|
442
|
+
listExtensions,
|
|
443
|
+
getAuthSettings,
|
|
444
|
+
getStorageSettings,
|
|
445
|
+
getRealtimeSettings,
|
|
446
|
+
findPgDumpPath
|
|
447
|
+
};
|