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 +1 -1
- package/src/commands/backup.js +93 -43
package/package.json
CHANGED
package/src/commands/backup.js
CHANGED
|
@@ -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
|
-
// ✅
|
|
266
|
-
const
|
|
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 (
|
|
269
|
-
console.log(chalk.yellow(` ⚠️ Erro ao listar Edge Functions: ${
|
|
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
|
|
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 (
|
|
294
|
-
console.log(chalk.yellow(` ⚠️ Erro ao baixar ${func.name}: ${
|
|
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
|
|
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.
|
|
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(
|
|
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
|
|
347
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(`
|
|
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
|
-
//
|
|
383
|
-
const
|
|
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 (
|
|
386
|
-
console.log(chalk.yellow(` ⚠️ Erro ao listar buckets: ${
|
|
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
|
|
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
|
|
398
|
-
|
|
399
|
-
|
|
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
|
-
|
|
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: [] };
|