smoonb 0.0.73 → 0.0.75
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/index.js +62 -65
- package/src/commands/backup/steps/00-docker-validation.js +6 -4
- package/src/commands/backup/steps/01-database.js +6 -3
- package/src/commands/backup/steps/02-database-separated.js +11 -8
- package/src/commands/backup/steps/03-database-settings.js +6 -3
- package/src/commands/backup/steps/04-auth-settings.js +6 -3
- package/src/commands/backup/steps/05-realtime-settings.js +5 -2
- package/src/commands/backup/steps/06-storage.js +28 -25
- package/src/commands/backup/steps/07-custom-roles.js +6 -3
- package/src/commands/backup/steps/08-edge-functions.js +14 -10
- package/src/commands/backup/steps/09-supabase-temp.js +9 -6
- package/src/commands/backup/steps/10-migrations.js +13 -9
- package/src/commands/restore/steps/00-backup-selection.js +4 -2
- package/src/commands/restore/steps/01-components-selection.js +30 -28
- package/src/commands/restore/steps/03-database.js +19 -16
- package/src/commands/restore/steps/04-edge-functions.js +16 -13
- package/src/commands/restore/steps/05-auth-settings.js +9 -6
- package/src/commands/restore/steps/06-storage.js +47 -40
- package/src/commands/restore/steps/07-database-settings.js +10 -7
- package/src/commands/restore/steps/08-realtime-settings.js +9 -6
- package/src/i18n/locales/en.json +328 -1
- package/src/i18n/locales/pt-BR.json +327 -1
- package/src/interactive/envMapper.js +30 -25
package/package.json
CHANGED
|
@@ -79,10 +79,10 @@ module.exports = async (options) => {
|
|
|
79
79
|
try {
|
|
80
80
|
await fs.access(envPath);
|
|
81
81
|
await backupEnvFile(envPath, envBackupPath);
|
|
82
|
-
console.log(chalk.blue(`📁
|
|
82
|
+
console.log(chalk.blue(`📁 ${getT('env.mapping.backupCreated', { path: path.relative(process.cwd(), envBackupPath) })}`));
|
|
83
83
|
} catch {
|
|
84
84
|
// Arquivo não existe, não fazer backup
|
|
85
|
-
console.log(chalk.yellow('
|
|
85
|
+
console.log(chalk.yellow(`⚠️ ${getT('env.mapping.fileNotFound')}`));
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
const expectedKeys = [
|
|
@@ -98,7 +98,7 @@ module.exports = async (options) => {
|
|
|
98
98
|
const { finalEnv, dePara } = await mapEnvVariablesInteractively(currentEnv, expectedKeys);
|
|
99
99
|
await writeEnvFile(envPath, finalEnv);
|
|
100
100
|
await saveEnvMap(dePara, path.join(backupDir, 'env', 'env-map.json'));
|
|
101
|
-
console.log(chalk.green('
|
|
101
|
+
console.log(chalk.green(`✅ ${getT('env.mapping.updated')}`));
|
|
102
102
|
|
|
103
103
|
function getValue(expectedKey) {
|
|
104
104
|
const clientKey = Object.keys(dePara).find(k => dePara[k] === expectedKey);
|
|
@@ -124,33 +124,33 @@ module.exports = async (options) => {
|
|
|
124
124
|
const supabaseServiceKey = getValue('SUPABASE_SERVICE_ROLE_KEY');
|
|
125
125
|
|
|
126
126
|
if (!databaseUrl) {
|
|
127
|
-
console.log(chalk.red(
|
|
127
|
+
console.log(chalk.red(`❌ ${getT('backup.error.databaseUrlNotConfigured')}`));
|
|
128
128
|
console.log('');
|
|
129
|
-
console.log(chalk.yellow('
|
|
130
|
-
console.log(chalk.yellow(
|
|
131
|
-
console.log(chalk.yellow(
|
|
129
|
+
console.log(chalk.yellow(`📋 ${getT('backup.error.databaseUrlInstructions')}`));
|
|
130
|
+
console.log(chalk.yellow(` 1. ${getT('backup.error.databaseUrlStep1')}`));
|
|
131
|
+
console.log(chalk.yellow(` 2. ${getT('backup.error.databaseUrlStep2')}`));
|
|
132
132
|
console.log('');
|
|
133
|
-
console.log(chalk.blue(
|
|
134
|
-
console.log(chalk.gray('
|
|
133
|
+
console.log(chalk.blue(`💡 ${getT('backup.error.databaseUrlExample')}:`));
|
|
134
|
+
console.log(chalk.gray(` ${getT('backup.error.databaseUrlExampleValue')}`));
|
|
135
135
|
console.log('');
|
|
136
|
-
console.log(chalk.red(
|
|
136
|
+
console.log(chalk.red(`🚫 ${getT('backup.error.databaseUrlCancelled')}`));
|
|
137
137
|
process.exit(1);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
if (!accessToken) {
|
|
141
|
-
console.log(chalk.red(
|
|
141
|
+
console.log(chalk.red(`❌ ${getT('backup.error.accessTokenNotConfigured')}`));
|
|
142
142
|
console.log('');
|
|
143
|
-
console.log(chalk.yellow('
|
|
144
|
-
console.log(chalk.yellow(
|
|
145
|
-
console.log(chalk.yellow(
|
|
146
|
-
console.log(chalk.yellow(
|
|
143
|
+
console.log(chalk.yellow(`📋 ${getT('backup.error.accessTokenInstructions')}`));
|
|
144
|
+
console.log(chalk.yellow(` 1. ${getT('backup.error.accessTokenStep1')}`));
|
|
145
|
+
console.log(chalk.yellow(` 2. ${getT('backup.error.accessTokenStep2')}`));
|
|
146
|
+
console.log(chalk.yellow(` 3. ${getT('backup.error.accessTokenStep3')}`));
|
|
147
147
|
console.log('');
|
|
148
|
-
console.log(chalk.blue(
|
|
149
|
-
console.log(chalk.gray('
|
|
150
|
-
console.log(chalk.gray('
|
|
151
|
-
console.log(chalk.gray(
|
|
148
|
+
console.log(chalk.blue(`🔗 ${getT('backup.error.accessTokenHowTo')}:`));
|
|
149
|
+
console.log(chalk.gray(` ${getT('backup.error.accessTokenStep1Detail')}`));
|
|
150
|
+
console.log(chalk.gray(` ${getT('backup.error.accessTokenStep2Detail')}`));
|
|
151
|
+
console.log(chalk.gray(` ${getT('backup.error.accessTokenStep3Detail')}`));
|
|
152
152
|
console.log('');
|
|
153
|
-
console.log(chalk.red(
|
|
153
|
+
console.log(chalk.red(`🚫 ${getT('backup.error.accessTokenCancelled')}`));
|
|
154
154
|
process.exit(1);
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -158,32 +158,32 @@ module.exports = async (options) => {
|
|
|
158
158
|
const flags = await askComponentsFlags();
|
|
159
159
|
|
|
160
160
|
// Mostrar resumo e pedir confirmação final
|
|
161
|
-
console.log(chalk.cyan(
|
|
162
|
-
console.log(chalk.white(` ✅
|
|
161
|
+
console.log(chalk.cyan(`\n📋 ${getT('backup.summary.title')}\n`));
|
|
162
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.edgeFunctions', { value: flags.includeFunctions ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
163
163
|
if (flags.includeFunctions) {
|
|
164
|
-
console.log(chalk.white(` 🗑️
|
|
164
|
+
console.log(chalk.white(` 🗑️ ${getT('backup.summary.edgeFunctionsCleanup', { value: flags.cleanFunctions ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
165
165
|
}
|
|
166
|
-
console.log(chalk.white(` ✅
|
|
166
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.temp', { value: flags.includeTemp ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
167
167
|
if (flags.includeTemp) {
|
|
168
|
-
console.log(chalk.white(` 🗑️
|
|
168
|
+
console.log(chalk.white(` 🗑️ ${getT('backup.summary.tempCleanup', { value: flags.cleanTemp ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
169
169
|
}
|
|
170
|
-
console.log(chalk.white(` ✅
|
|
170
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.migrations', { value: flags.includeMigrations ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
171
171
|
if (flags.includeMigrations) {
|
|
172
|
-
console.log(chalk.white(` 🗑️
|
|
172
|
+
console.log(chalk.white(` 🗑️ ${getT('backup.summary.migrationsCleanup', { value: flags.cleanMigrations ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
173
173
|
}
|
|
174
|
-
console.log(chalk.white(` ✅
|
|
175
|
-
console.log(chalk.white(` ✅
|
|
176
|
-
console.log(chalk.white(` ✅
|
|
177
|
-
console.log(chalk.white(` 📁
|
|
174
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.storage', { value: flags.includeStorage ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
175
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.auth', { value: flags.includeAuth ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
176
|
+
console.log(chalk.white(` ✅ ${getT('backup.summary.realtime', { value: flags.includeRealtime ? getT('backup.summary.yes') : getT('backup.summary.no') })}`));
|
|
177
|
+
console.log(chalk.white(` 📁 ${getT('backup.summary.backupDir', { path: finalBackupDir })}\n`));
|
|
178
178
|
|
|
179
|
-
const finalOk = await confirm('
|
|
179
|
+
const finalOk = await confirm(getT('backup.summary.confirm'), true);
|
|
180
180
|
|
|
181
181
|
if (!finalOk) {
|
|
182
|
-
console.log(chalk.red('
|
|
182
|
+
console.log(chalk.red(`🚫 ${getT('disclaimer.operationCancelled')}`));
|
|
183
183
|
process.exit(1);
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
console.log(chalk.blue(`\n🚀
|
|
186
|
+
console.log(chalk.blue(`\n🚀 ${getT('backup.start.title', { projectId })}`));
|
|
187
187
|
|
|
188
188
|
// Criar contexto compartilhado para as etapas
|
|
189
189
|
const context = {
|
|
@@ -214,8 +214,8 @@ module.exports = async (options) => {
|
|
|
214
214
|
};
|
|
215
215
|
|
|
216
216
|
// Executar todas as etapas na ordem
|
|
217
|
-
console.log(chalk.blue(`📁
|
|
218
|
-
console.log(chalk.white(`🐳
|
|
217
|
+
console.log(chalk.blue(`📁 ${getT('backup.start.directory', { path: finalBackupDir })}`));
|
|
218
|
+
console.log(chalk.white(`🐳 ${getT('backup.start.docker')}`));
|
|
219
219
|
|
|
220
220
|
// Contar etapas totais para numeração
|
|
221
221
|
// Etapas fixas: Database, Database Separado, Database Settings, Custom Roles (4)
|
|
@@ -225,13 +225,13 @@ module.exports = async (options) => {
|
|
|
225
225
|
|
|
226
226
|
// 1. Backup Database via pg_dumpall Docker
|
|
227
227
|
stepNumber++;
|
|
228
|
-
console.log(chalk.blue(`\n📊 ${stepNumber}/${totalSteps} -
|
|
228
|
+
console.log(chalk.blue(`\n📊 ${stepNumber}/${totalSteps} - ${getT('backup.steps.database.title')}`));
|
|
229
229
|
const databaseResult = await step01Database(context);
|
|
230
230
|
manifest.components.database = databaseResult;
|
|
231
231
|
|
|
232
232
|
// 2. Backup Database Separado
|
|
233
233
|
stepNumber++;
|
|
234
|
-
console.log(chalk.blue(`\n📊 ${stepNumber}/${totalSteps} -
|
|
234
|
+
console.log(chalk.blue(`\n📊 ${stepNumber}/${totalSteps} - ${getT('backup.steps.database.separated.title')}`));
|
|
235
235
|
const dbSeparatedResult = await step02DatabaseSeparated(context);
|
|
236
236
|
manifest.components.database_separated = {
|
|
237
237
|
success: dbSeparatedResult.success,
|
|
@@ -242,14 +242,14 @@ module.exports = async (options) => {
|
|
|
242
242
|
|
|
243
243
|
// 3. Backup Database Settings
|
|
244
244
|
stepNumber++;
|
|
245
|
-
console.log(chalk.blue(`\n🔧 ${stepNumber}/${totalSteps} -
|
|
245
|
+
console.log(chalk.blue(`\n🔧 ${stepNumber}/${totalSteps} - ${getT('backup.steps.databaseSettings.title')}`));
|
|
246
246
|
const databaseSettingsResult = await step03DatabaseSettings(context);
|
|
247
247
|
manifest.components.database_settings = databaseSettingsResult;
|
|
248
248
|
|
|
249
249
|
// 4. Backup Auth Settings
|
|
250
250
|
if (flags?.includeAuth) {
|
|
251
251
|
stepNumber++;
|
|
252
|
-
console.log(chalk.blue(`\n🔐 ${stepNumber}/${totalSteps} -
|
|
252
|
+
console.log(chalk.blue(`\n🔐 ${stepNumber}/${totalSteps} - ${getT('backup.steps.auth.title')}`));
|
|
253
253
|
const authResult = await step04AuthSettings(context);
|
|
254
254
|
manifest.components.auth_settings = authResult;
|
|
255
255
|
}
|
|
@@ -257,7 +257,7 @@ module.exports = async (options) => {
|
|
|
257
257
|
// 5. Backup Realtime Settings
|
|
258
258
|
if (flags?.includeRealtime) {
|
|
259
259
|
stepNumber++;
|
|
260
|
-
console.log(chalk.blue(`\n🔄 ${stepNumber}/${totalSteps} -
|
|
260
|
+
console.log(chalk.blue(`\n🔄 ${stepNumber}/${totalSteps} - ${getT('backup.steps.realtime.title')}`));
|
|
261
261
|
const realtimeResult = await step05RealtimeSettings(context);
|
|
262
262
|
manifest.components.realtime = realtimeResult;
|
|
263
263
|
}
|
|
@@ -265,21 +265,21 @@ module.exports = async (options) => {
|
|
|
265
265
|
// 6. Backup Storage
|
|
266
266
|
if (flags?.includeStorage) {
|
|
267
267
|
stepNumber++;
|
|
268
|
-
console.log(chalk.blue(`\n📦 ${stepNumber}/${totalSteps} -
|
|
268
|
+
console.log(chalk.blue(`\n📦 ${stepNumber}/${totalSteps} - ${getT('backup.steps.storage.title')}`));
|
|
269
269
|
const storageResult = await step06Storage(context);
|
|
270
270
|
manifest.components.storage = storageResult;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
// 7. Backup Custom Roles
|
|
274
274
|
stepNumber++;
|
|
275
|
-
console.log(chalk.blue(`\n👥 ${stepNumber}/${totalSteps} -
|
|
275
|
+
console.log(chalk.blue(`\n👥 ${stepNumber}/${totalSteps} - ${getT('backup.steps.roles.title')}`));
|
|
276
276
|
const rolesResult = await step07CustomRoles(context);
|
|
277
277
|
manifest.components.custom_roles = rolesResult;
|
|
278
278
|
|
|
279
279
|
// 8. Backup Edge Functions
|
|
280
280
|
if (flags?.includeFunctions) {
|
|
281
281
|
stepNumber++;
|
|
282
|
-
console.log(chalk.blue(`\n⚡ ${stepNumber}/${totalSteps} -
|
|
282
|
+
console.log(chalk.blue(`\n⚡ ${stepNumber}/${totalSteps} - ${getT('backup.steps.functions.title')}`));
|
|
283
283
|
const functionsResult = await step08EdgeFunctions(context);
|
|
284
284
|
manifest.components.edge_functions = functionsResult;
|
|
285
285
|
}
|
|
@@ -287,7 +287,7 @@ module.exports = async (options) => {
|
|
|
287
287
|
// 9. Backup Supabase .temp
|
|
288
288
|
if (flags?.includeTemp) {
|
|
289
289
|
stepNumber++;
|
|
290
|
-
console.log(chalk.blue(`\n📁 ${stepNumber}/${totalSteps} -
|
|
290
|
+
console.log(chalk.blue(`\n📁 ${stepNumber}/${totalSteps} - ${getT('backup.steps.temp.title')}`));
|
|
291
291
|
const supabaseTempResult = await step09SupabaseTemp(context);
|
|
292
292
|
manifest.components.supabase_temp = supabaseTempResult;
|
|
293
293
|
}
|
|
@@ -295,7 +295,7 @@ module.exports = async (options) => {
|
|
|
295
295
|
// 10. Backup Migrations
|
|
296
296
|
if (flags?.includeMigrations) {
|
|
297
297
|
stepNumber++;
|
|
298
|
-
console.log(chalk.blue(`\n📋 ${stepNumber}/${totalSteps} -
|
|
298
|
+
console.log(chalk.blue(`\n📋 ${stepNumber}/${totalSteps} - ${getT('backup.steps.migrations.title')}`));
|
|
299
299
|
const migrationsResult = await step10Migrations(context);
|
|
300
300
|
manifest.components.migrations = migrationsResult;
|
|
301
301
|
}
|
|
@@ -304,27 +304,24 @@ module.exports = async (options) => {
|
|
|
304
304
|
await writeJson(path.join(finalBackupDir, 'backup-manifest.json'), manifest);
|
|
305
305
|
|
|
306
306
|
// Exibir resumo final (na ordem de captura)
|
|
307
|
-
console.log(chalk.green(
|
|
308
|
-
console.log(chalk.blue(`📁
|
|
309
|
-
console.log(chalk.green(`📊
|
|
310
|
-
console.log(chalk.green(`📊
|
|
311
|
-
console.log(chalk.green(`🔧
|
|
307
|
+
console.log(chalk.green(`\n🎉 ${getT('backup.complete.title')}`));
|
|
308
|
+
console.log(chalk.blue(`📁 ${getT('backup.complete.location', { path: finalBackupDir })}`));
|
|
309
|
+
console.log(chalk.green(`📊 ${getT('backup.complete.database', { fileName: databaseResult.fileName, size: `${databaseResult.size} KB` })}`));
|
|
310
|
+
console.log(chalk.green(`📊 ${getT('backup.complete.databaseSql', { count: dbSeparatedResult.files?.length || 0, size: `${dbSeparatedResult.totalSizeKB} KB` })}`));
|
|
311
|
+
console.log(chalk.green(`🔧 ${getT('backup.complete.databaseSettings', { fileName: databaseSettingsResult.fileName, size: `${databaseSettingsResult.size} KB` })}`));
|
|
312
312
|
|
|
313
313
|
if (flags?.includeAuth && manifest.components.auth_settings) {
|
|
314
|
-
|
|
315
|
-
console.log(chalk.green(`🔐 Auth Settings: ${authResult.success ? 'Exportadas via API' : 'Falharam'}`));
|
|
314
|
+
console.log(chalk.green(`🔐 ${getT('backup.complete.auth')}`));
|
|
316
315
|
}
|
|
317
316
|
|
|
318
317
|
// Determinar mensagem correta baseada no método usado
|
|
319
318
|
if (flags?.includeRealtime && manifest.components.realtime) {
|
|
320
319
|
const realtimeResult = manifest.components.realtime;
|
|
321
|
-
let realtimeMessage = '
|
|
322
|
-
if (realtimeResult.success) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
realtimeMessage = 'Configurações capturadas interativamente';
|
|
327
|
-
}
|
|
320
|
+
let realtimeMessage = getT('backup.complete.realtime');
|
|
321
|
+
if (!realtimeResult.success) {
|
|
322
|
+
realtimeMessage = 'Falharam';
|
|
323
|
+
} else if (options.skipRealtime) {
|
|
324
|
+
realtimeMessage = 'Configurações copiadas do backup anterior';
|
|
328
325
|
}
|
|
329
326
|
console.log(chalk.green(`🔄 Realtime: ${realtimeMessage}`));
|
|
330
327
|
}
|
|
@@ -332,27 +329,27 @@ module.exports = async (options) => {
|
|
|
332
329
|
if (flags?.includeStorage && manifest.components.storage) {
|
|
333
330
|
const storageResult = manifest.components.storage;
|
|
334
331
|
if (storageResult.zipFile) {
|
|
335
|
-
console.log(chalk.green(`📦
|
|
332
|
+
console.log(chalk.green(`📦 ${getT('backup.complete.storage', { buckets: storageResult.buckets?.length || 0, files: storageResult.totalFiles || 0, zipFile: storageResult.zipFile, size: `${storageResult.zipSizeMB || 0} MB` })}`));
|
|
336
333
|
} else {
|
|
337
334
|
console.log(chalk.green(`📦 Storage: ${storageResult.buckets?.length || 0} buckets verificados via API (apenas metadados)`));
|
|
338
335
|
}
|
|
339
336
|
}
|
|
340
337
|
|
|
341
|
-
console.log(chalk.green(`👥
|
|
338
|
+
console.log(chalk.green(`👥 ${getT('backup.complete.roles', { count: rolesResult.roles?.length || 0 })}`));
|
|
342
339
|
|
|
343
340
|
if (flags?.includeFunctions && manifest.components.edge_functions) {
|
|
344
341
|
const functionsResult = manifest.components.edge_functions;
|
|
345
|
-
console.log(chalk.green(`⚡
|
|
342
|
+
console.log(chalk.green(`⚡ ${getT('backup.complete.functions', { downloaded: functionsResult.success_count || 0, total: functionsResult.functions_count || 0 })}`));
|
|
346
343
|
}
|
|
347
344
|
|
|
348
345
|
if (flags?.includeTemp && manifest.components.supabase_temp) {
|
|
349
346
|
const tempResult = manifest.components.supabase_temp;
|
|
350
|
-
console.log(chalk.green(`📁
|
|
347
|
+
console.log(chalk.green(`📁 ${getT('backup.complete.temp', { count: tempResult.file_count || 0 })}`));
|
|
351
348
|
}
|
|
352
349
|
|
|
353
350
|
if (flags?.includeMigrations && manifest.components.migrations) {
|
|
354
351
|
const migrationsResult = manifest.components.migrations;
|
|
355
|
-
console.log(chalk.green(`📋
|
|
352
|
+
console.log(chalk.green(`📋 ${getT('backup.complete.migrations', { count: migrationsResult.file_count || 0 })}`));
|
|
356
353
|
}
|
|
357
354
|
|
|
358
355
|
// report.json
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const { canPerformCompleteBackup } = require('../../../utils/docker');
|
|
3
3
|
const { showDockerMessagesAndExit } = require('../utils');
|
|
4
|
+
const { t } = require('../../../i18n');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Etapa 0: Validação Docker
|
|
7
8
|
* Deve ocorrer antes de tudo
|
|
8
9
|
*/
|
|
9
10
|
module.exports = async () => {
|
|
10
|
-
|
|
11
|
-
console.log(chalk.
|
|
11
|
+
const getT = global.smoonbI18n?.t || t;
|
|
12
|
+
console.log(chalk.blue(`\n🐳 ${getT('docker.validation.title')}`));
|
|
13
|
+
console.log(chalk.cyan(`🔍 ${getT('docker.validation.checking')}`));
|
|
12
14
|
|
|
13
15
|
const backupCapability = await canPerformCompleteBackup();
|
|
14
16
|
|
|
@@ -16,8 +18,8 @@ module.exports = async () => {
|
|
|
16
18
|
showDockerMessagesAndExit(backupCapability.reason);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
console.log(chalk.green(
|
|
20
|
-
console.log(chalk.white(`🐳
|
|
21
|
+
console.log(chalk.green(`✅ ${getT('docker.validation.detected')}`));
|
|
22
|
+
console.log(chalk.white(`🐳 ${getT('docker.validation.version', { version: backupCapability.dockerStatus.version })}`));
|
|
21
23
|
|
|
22
24
|
return { success: true };
|
|
23
25
|
};
|
|
@@ -2,13 +2,15 @@ const chalk = require('chalk');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs').promises;
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
+
const { t } = require('../../../i18n');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Etapa 1: Backup Database via pg_dumpall Docker (idêntico ao Dashboard)
|
|
8
9
|
*/
|
|
9
10
|
module.exports = async ({ databaseUrl, backupDir }) => {
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
+
const getT = global.smoonbI18n?.t || t;
|
|
13
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.creating')}`));
|
|
12
14
|
|
|
13
15
|
// Extrair credenciais da databaseUrl
|
|
14
16
|
const urlMatch = databaseUrl.match(/postgresql:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)/);
|
|
@@ -45,7 +47,7 @@ module.exports = async ({ databaseUrl, backupDir }) => {
|
|
|
45
47
|
`-f /host/${fileName}`
|
|
46
48
|
].join(' ');
|
|
47
49
|
|
|
48
|
-
console.log(chalk.white(
|
|
50
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.executing')}`));
|
|
49
51
|
execSync(dockerCmd, { stdio: 'pipe' });
|
|
50
52
|
|
|
51
53
|
// Compactar igual ao Supabase Dashboard
|
|
@@ -65,7 +67,8 @@ module.exports = async ({ databaseUrl, backupDir }) => {
|
|
|
65
67
|
|
|
66
68
|
return { success: true, size: sizeKB, fileName: finalFileName };
|
|
67
69
|
} catch (error) {
|
|
68
|
-
|
|
70
|
+
const getT = global.smoonbI18n?.t || t;
|
|
71
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.database.error', { message: error.message })}`));
|
|
69
72
|
return { success: false };
|
|
70
73
|
}
|
|
71
74
|
};
|
|
@@ -2,20 +2,22 @@ const chalk = require('chalk');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs').promises;
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
+
const { t } = require('../../../i18n');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Etapa 2: Backup Database Separado (SQL files para troubleshooting)
|
|
8
9
|
*/
|
|
9
10
|
module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
+
const getT = global.smoonbI18n?.t || t;
|
|
13
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.separated.creating')}`));
|
|
12
14
|
|
|
13
15
|
const dbUrl = databaseUrl;
|
|
14
16
|
const files = [];
|
|
15
17
|
let totalSizeKB = 0;
|
|
16
18
|
|
|
17
19
|
// 1. Backup do Schema
|
|
18
|
-
console.log(chalk.white(
|
|
20
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.separated.exportingSchema')}`));
|
|
19
21
|
const schemaFile = path.join(backupDir, 'schema.sql');
|
|
20
22
|
|
|
21
23
|
try {
|
|
@@ -29,11 +31,11 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
|
|
|
29
31
|
totalSizeKB += parseFloat(sizeKB);
|
|
30
32
|
console.log(chalk.green(` ✅ Schema: ${sizeKB} KB`));
|
|
31
33
|
} catch (error) {
|
|
32
|
-
console.log(chalk.yellow(` ⚠️
|
|
34
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.database.separated.schemaError', { message: error.message })}`));
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
// 2. Backup dos Dados
|
|
36
|
-
console.log(chalk.white(
|
|
38
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.separated.exportingData')}`));
|
|
37
39
|
const dataFile = path.join(backupDir, 'data.sql');
|
|
38
40
|
|
|
39
41
|
try {
|
|
@@ -47,11 +49,11 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
|
|
|
47
49
|
totalSizeKB += parseFloat(sizeKB);
|
|
48
50
|
console.log(chalk.green(` ✅ Data: ${sizeKB} KB`));
|
|
49
51
|
} catch (error) {
|
|
50
|
-
console.log(chalk.yellow(` ⚠️
|
|
52
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.database.separated.dataError', { message: error.message })}`));
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
// 3. Backup dos Roles
|
|
54
|
-
console.log(chalk.white(
|
|
56
|
+
console.log(chalk.white(` - ${getT('backup.steps.database.separated.exportingRoles')}`));
|
|
55
57
|
const rolesFile = path.join(backupDir, 'roles.sql');
|
|
56
58
|
|
|
57
59
|
try {
|
|
@@ -65,7 +67,7 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
|
|
|
65
67
|
totalSizeKB += parseFloat(sizeKB);
|
|
66
68
|
console.log(chalk.green(` ✅ Roles: ${sizeKB} KB`));
|
|
67
69
|
} catch (error) {
|
|
68
|
-
console.log(chalk.yellow(` ⚠️
|
|
70
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.database.separated.rolesError', { message: error.message })}`));
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
return {
|
|
@@ -75,7 +77,8 @@ module.exports = async ({ databaseUrl, backupDir, accessToken }) => {
|
|
|
75
77
|
};
|
|
76
78
|
|
|
77
79
|
} catch (error) {
|
|
78
|
-
|
|
80
|
+
const getT = global.smoonbI18n?.t || t;
|
|
81
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.database.separated.error', { message: error.message })}`));
|
|
79
82
|
return { success: false, files: [], totalSizeKB: '0.0' };
|
|
80
83
|
}
|
|
81
84
|
};
|
|
@@ -2,13 +2,15 @@ const chalk = require('chalk');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs').promises;
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
+
const { t } = require('../../../i18n');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Etapa 3: Backup Database Extensions and Settings via SQL
|
|
8
9
|
*/
|
|
9
10
|
module.exports = async ({ databaseUrl, projectId, backupDir }) => {
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
+
const getT = global.smoonbI18n?.t || t;
|
|
13
|
+
console.log(chalk.white(` - ${getT('backup.steps.databaseSettings.capturing')}`));
|
|
12
14
|
|
|
13
15
|
// Extrair credenciais da databaseUrl
|
|
14
16
|
const urlMatch = databaseUrl.match(/postgresql:\/\/([^:]+):([^@]+)@([^:]+):(\d+)\/(.+)/);
|
|
@@ -125,7 +127,7 @@ AND EXISTS (
|
|
|
125
127
|
'-A' // Unaligned output
|
|
126
128
|
].join(' ');
|
|
127
129
|
|
|
128
|
-
console.log(chalk.white(
|
|
130
|
+
console.log(chalk.white(` - ${getT('backup.steps.databaseSettings.executing')}`));
|
|
129
131
|
const output = execSync(dockerCmd, { stdio: 'pipe', encoding: 'utf8' });
|
|
130
132
|
|
|
131
133
|
// Processar output e criar JSON estruturado
|
|
@@ -171,7 +173,8 @@ AND EXISTS (
|
|
|
171
173
|
|
|
172
174
|
return { success: true, size: sizeKB, fileName: fileName };
|
|
173
175
|
} catch (error) {
|
|
174
|
-
|
|
176
|
+
const getT = global.smoonbI18n?.t || t;
|
|
177
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.databaseSettings.error', { message: error.message })}`));
|
|
175
178
|
return { success: false };
|
|
176
179
|
}
|
|
177
180
|
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { writeJson } = require('../../../utils/fsx');
|
|
4
|
+
const { t } = require('../../../i18n');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Etapa 4: Backup Auth Settings via Management API
|
|
7
8
|
*/
|
|
8
9
|
module.exports = async ({ projectId, accessToken, backupDir }) => {
|
|
9
10
|
try {
|
|
10
|
-
|
|
11
|
+
const getT = global.smoonbI18n?.t || t;
|
|
12
|
+
console.log(chalk.white(` - ${getT('backup.steps.auth.exporting')}`));
|
|
11
13
|
|
|
12
14
|
// Usar fetch direto para Management API com Personal Access Token
|
|
13
15
|
const authResponse = await fetch(`https://api.supabase.com/v1/projects/${projectId}/config/auth`, {
|
|
@@ -18,7 +20,7 @@ module.exports = async ({ projectId, accessToken, backupDir }) => {
|
|
|
18
20
|
});
|
|
19
21
|
|
|
20
22
|
if (!authResponse.ok) {
|
|
21
|
-
console.log(chalk.yellow(` ⚠️
|
|
23
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.auth.getError', { status: authResponse.status, statusText: authResponse.statusText })}`));
|
|
22
24
|
return { success: false };
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -36,7 +38,8 @@ module.exports = async ({ projectId, accessToken, backupDir }) => {
|
|
|
36
38
|
return { success: true };
|
|
37
39
|
|
|
38
40
|
} catch (error) {
|
|
39
|
-
|
|
41
|
+
const getT = global.smoonbI18n?.t || t;
|
|
42
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.auth.error', { message: error.message })}`));
|
|
40
43
|
return { success: false };
|
|
41
44
|
}
|
|
42
45
|
};
|
|
@@ -2,13 +2,15 @@ const chalk = require('chalk');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs').promises;
|
|
4
4
|
const { captureRealtimeSettings } = require('../../../utils/realtime-settings');
|
|
5
|
+
const { t } = require('../../../i18n');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Etapa 5: Backup Realtime Settings via Captura Interativa
|
|
8
9
|
*/
|
|
9
10
|
module.exports = async ({ projectId, backupDir, options }) => {
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
+
const getT = global.smoonbI18n?.t || t;
|
|
13
|
+
console.log(chalk.white(` - ${getT('backup.steps.realtime.capturing')}`));
|
|
12
14
|
|
|
13
15
|
const result = await captureRealtimeSettings(projectId, backupDir, options?.skipRealtime);
|
|
14
16
|
|
|
@@ -19,7 +21,8 @@ module.exports = async ({ projectId, backupDir, options }) => {
|
|
|
19
21
|
|
|
20
22
|
return { success: true, settings: result };
|
|
21
23
|
} catch (error) {
|
|
22
|
-
|
|
24
|
+
const getT = global.smoonbI18n?.t || t;
|
|
25
|
+
console.log(chalk.yellow(` ⚠️ ${getT('backup.steps.realtime.error', { message: error.message })}`));
|
|
23
26
|
return { success: false };
|
|
24
27
|
}
|
|
25
28
|
};
|