smoonb 0.0.15 → 0.0.16

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.15",
3
+ "version": "0.0.16",
4
4
  "description": "Complete Supabase backup and migration tool - EXPERIMENTAL VERSION - USE AT YOUR OWN RISK",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -256,20 +256,27 @@ async function backupDatabaseWithPgDump(databaseUrl, backupDir, pgDumpPath) {
256
256
  // Backup das Edge Functions via Supabase API
257
257
  async function backupEdgeFunctions(config, backupDir) {
258
258
  try {
259
- const supabase = createClient(config.supabase.url, config.supabase.serviceKey);
260
259
  const functionsDir = path.join(backupDir, 'edge-functions');
261
260
  await ensureDir(functionsDir);
262
261
 
263
- console.log(chalk.gray(' - Listando Edge Functions...'));
262
+ console.log(chalk.gray(' - Listando Edge Functions via Management API...'));
264
263
 
265
- // ✅ Descobrir dinamicamente quantas functions existem
266
- const { data: functions, error } = await supabase.functions.list();
264
+ // ✅ Usar fetch direto para Management API
265
+ const functionsResponse = await fetch(`https://api.supabase.com/v1/projects/${config.supabase.projectId}/functions`, {
266
+ headers: {
267
+ 'Authorization': `Bearer ${config.supabase.serviceKey}`,
268
+ 'apikey': config.supabase.serviceKey,
269
+ 'Content-Type': 'application/json'
270
+ }
271
+ });
267
272
 
268
- if (error) {
269
- console.log(chalk.yellow(` ⚠️ Erro ao listar Edge Functions: ${error.message}`));
273
+ if (!functionsResponse.ok) {
274
+ console.log(chalk.yellow(` ⚠️ Erro ao listar Edge Functions: ${functionsResponse.status} ${functionsResponse.statusText}`));
270
275
  return { success: false, functions: [] };
271
276
  }
272
277
 
278
+ const functions = await functionsResponse.json();
279
+
273
280
  if (!functions || functions.length === 0) {
274
281
  console.log(chalk.gray(' - Nenhuma Edge Function encontrada'));
275
282
  await writeJson(path.join(functionsDir, 'README.md'), {
@@ -287,14 +294,22 @@ async function backupEdgeFunctions(config, backupDir) {
287
294
  try {
288
295
  console.log(chalk.gray(` - Baixando: ${func.name}`));
289
296
 
290
- // ✅ Baixar código da function
291
- const { data: functionData, error: functionError } = await supabase.functions.get(func.slug);
297
+ // ✅ Baixar código da function via Management API
298
+ const functionResponse = await fetch(`https://api.supabase.com/v1/projects/${config.supabase.projectId}/functions/${func.name}`, {
299
+ headers: {
300
+ 'Authorization': `Bearer ${config.supabase.serviceKey}`,
301
+ 'apikey': config.supabase.serviceKey,
302
+ 'Content-Type': 'application/json'
303
+ }
304
+ });
292
305
 
293
- if (functionError) {
294
- console.log(chalk.yellow(` ⚠️ Erro ao baixar ${func.name}: ${functionError.message}`));
306
+ if (!functionResponse.ok) {
307
+ console.log(chalk.yellow(` ⚠️ Erro ao baixar ${func.name}: ${functionResponse.status} ${functionResponse.statusText}`));
295
308
  continue;
296
309
  }
297
310
 
311
+ const functionData = await functionResponse.json();
312
+
298
313
  // ✅ Salvar arquivos dinamicamente
299
314
  const funcDir = path.join(functionsDir, func.name);
300
315
  await ensureDir(funcDir);
@@ -307,7 +322,7 @@ async function backupEdgeFunctions(config, backupDir) {
307
322
  await fs.promises.writeFile(filePath, file.content);
308
323
  }
309
324
  } else if (functionData && functionData.code) {
310
- // Fallback para API antiga
325
+ // Fallback para estrutura simples
311
326
  const indexPath = path.join(funcDir, 'index.ts');
312
327
  await fs.promises.writeFile(indexPath, functionData.code);
313
328
 
@@ -315,11 +330,15 @@ async function backupEdgeFunctions(config, backupDir) {
315
330
  const denoPath = path.join(funcDir, 'deno.json');
316
331
  await writeJson(denoPath, functionData.deno_config);
317
332
  }
333
+ } else {
334
+ // Criar arquivo placeholder se não houver código
335
+ const indexPath = path.join(funcDir, 'index.ts');
336
+ await fs.promises.writeFile(indexPath, `// Edge Function: ${func.name}\n// Code not available via API\n`);
318
337
  }
319
338
 
320
339
  downloadedFunctions.push({
321
340
  name: func.name,
322
- slug: func.slug,
341
+ slug: func.name,
323
342
  version: func.version || 'unknown',
324
343
  files: fs.existsSync(funcDir) ? fs.readdirSync(funcDir) : []
325
344
  });
@@ -332,8 +351,9 @@ async function backupEdgeFunctions(config, backupDir) {
332
351
 
333
352
  console.log(chalk.green(`✅ Edge Functions backupadas: ${downloadedFunctions.length} functions`));
334
353
  return { success: true, functions: downloadedFunctions };
354
+
335
355
  } catch (error) {
336
- console.log(chalk.yellow(`⚠️ Erro no backup das Edge Functions: ${error.message}`));
356
+ console.log(chalk.yellow(` ⚠️ Erro no backup das Edge Functions: ${error.message}`));
337
357
  return { success: false, functions: [] };
338
358
  }
339
359
  }
@@ -341,31 +361,37 @@ async function backupEdgeFunctions(config, backupDir) {
341
361
  // Backup das Auth Settings via Management API
342
362
  async function backupAuthSettings(config, backupDir) {
343
363
  try {
344
- console.log(chalk.gray(' - Exportando configurações de Auth...'));
364
+ console.log(chalk.gray(' - Exportando configurações de Auth via Management API...'));
345
365
 
346
- // Usar Management API para obter configurações de Auth
347
- const authSettingsPath = path.join(backupDir, 'auth-settings.json');
366
+ // Usar fetch direto para Management API
367
+ const authResponse = await fetch(`https://api.supabase.com/v1/projects/${config.supabase.projectId}/auth/settings`, {
368
+ headers: {
369
+ 'Authorization': `Bearer ${config.supabase.serviceKey}`,
370
+ 'apikey': config.supabase.serviceKey,
371
+ 'Content-Type': 'application/json'
372
+ }
373
+ });
348
374
 
349
- const authSettings = {
375
+ if (!authResponse.ok) {
376
+ console.log(chalk.yellow(` ⚠️ Erro ao obter Auth Settings: ${authResponse.status} ${authResponse.statusText}`));
377
+ return { success: false };
378
+ }
379
+
380
+ const authSettings = await authResponse.json();
381
+
382
+ // Salvar configurações de Auth
383
+ const authSettingsPath = path.join(backupDir, 'auth-settings.json');
384
+ await writeJson(authSettingsPath, {
350
385
  project_id: config.supabase.projectId,
351
386
  timestamp: new Date().toISOString(),
352
- settings: {
353
- // Configurações básicas que podemos obter
354
- site_url: config.supabase.url,
355
- jwt_secret: 'REDACTED', // Não expor secret
356
- smtp_settings: null,
357
- rate_limits: null,
358
- email_templates: null
359
- },
360
- note: 'Configurações completas requerem acesso ao Management API'
361
- };
387
+ settings: authSettings
388
+ });
362
389
 
363
- await writeJson(authSettingsPath, authSettings);
364
- console.log(chalk.green(' ✅ Auth Settings exportadas'));
365
-
390
+ console.log(chalk.green(`✅ Auth Settings exportadas: ${path.basename(authSettingsPath)}`));
366
391
  return { success: true };
392
+
367
393
  } catch (error) {
368
- console.log(chalk.yellow(` ⚠️ Erro ao exportar Auth Settings: ${error.message}`));
394
+ console.log(chalk.yellow(` ⚠️ Erro no backup das Auth Settings: ${error.message}`));
369
395
  return { success: false };
370
396
  }
371
397
  }
@@ -373,30 +399,54 @@ async function backupAuthSettings(config, backupDir) {
373
399
  // Backup do Storage via Supabase API
374
400
  async function backupStorage(config, backupDir) {
375
401
  try {
376
- const supabase = createClient(config.supabase.url, config.supabase.serviceKey);
377
402
  const storageDir = path.join(backupDir, 'storage');
378
403
  await ensureDir(storageDir);
379
404
 
380
- console.log(chalk.gray(' - Listando buckets de Storage...'));
405
+ console.log(chalk.gray(' - Listando buckets de Storage via Management API...'));
381
406
 
382
- // Listar buckets
383
- const { data: buckets, error } = await supabase.storage.listBuckets();
407
+ // Usar fetch direto para Management API
408
+ const storageResponse = await fetch(`https://api.supabase.com/v1/projects/${config.supabase.projectId}/storage/buckets`, {
409
+ headers: {
410
+ 'Authorization': `Bearer ${config.supabase.serviceKey}`,
411
+ 'apikey': config.supabase.serviceKey,
412
+ 'Content-Type': 'application/json'
413
+ }
414
+ });
384
415
 
385
- if (error) {
386
- console.log(chalk.yellow(` ⚠️ Erro ao listar buckets: ${error.message}`));
416
+ if (!storageResponse.ok) {
417
+ console.log(chalk.yellow(` ⚠️ Erro ao listar buckets: ${storageResponse.status} ${storageResponse.statusText}`));
387
418
  return { success: false, buckets: [] };
388
419
  }
389
420
 
390
- const processedBuckets = [];
421
+ const buckets = await storageResponse.json();
422
+
423
+ if (!buckets || buckets.length === 0) {
424
+ console.log(chalk.gray(' - Nenhum bucket encontrado'));
425
+ await writeJson(path.join(storageDir, 'README.md'), {
426
+ message: 'Nenhum bucket de Storage encontrado neste projeto'
427
+ });
428
+ return { success: true, buckets: [] };
429
+ }
430
+
431
+ console.log(chalk.gray(` - Encontrados ${buckets.length} buckets`));
391
432
 
392
433
  for (const bucket of buckets || []) {
393
434
  try {
394
435
  console.log(chalk.gray(` - Processando bucket: ${bucket.name}`));
395
436
 
396
- // Listar objetos do bucket
397
- const { data: objects, error: objectsError } = await supabase.storage
398
- .from(bucket.name)
399
- .list('', { limit: 1000 });
437
+ // Listar objetos do bucket via Management API
438
+ const objectsResponse = await fetch(`https://api.supabase.com/v1/projects/${config.supabase.projectId}/storage/buckets/${bucket.name}/objects`, {
439
+ headers: {
440
+ 'Authorization': `Bearer ${config.supabase.serviceKey}`,
441
+ 'apikey': config.supabase.serviceKey,
442
+ 'Content-Type': 'application/json'
443
+ }
444
+ });
445
+
446
+ let objects = [];
447
+ if (objectsResponse.ok) {
448
+ objects = await objectsResponse.json();
449
+ }
400
450
 
401
451
  const bucketInfo = {
402
452
  id: bucket.id,
@@ -422,7 +472,7 @@ async function backupStorage(config, backupDir) {
422
472
  }
423
473
  }
424
474
 
425
- return { success: true, buckets: processedBuckets };
475
+ console.log(chalk.green(`✅ Storage backupado: ${processedBuckets.length} buckets`));
426
476
  } catch (error) {
427
477
  console.log(chalk.yellow(`⚠️ Erro no backup do Storage: ${error.message}`));
428
478
  return { success: false, buckets: [] };