smoonb 0.0.71 → 0.0.72

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.
@@ -1,135 +1,143 @@
1
- const chalk = require('chalk');
2
- const fs = require('fs').promises;
3
- const path = require('path');
4
- const { showBetaBanner } = require('../utils/banner');
5
-
6
- // Exportar FUNÇÃO em vez de objeto Command
7
- module.exports = async (options) => {
8
- showBetaBanner();
9
-
10
- console.log(chalk.cyan.bold('⚙️ Configuração do smoonb...\n'));
11
-
12
- try {
13
- const configPath = path.join(process.cwd(), '.smoonbrc');
14
-
15
- if (options.init) {
16
- await initializeConfig(configPath);
17
- } else if (options.show) {
18
- await showConfig(configPath);
19
- } else {
20
- console.log(chalk.yellow('💡 Opções disponíveis:'));
21
- console.log(chalk.gray(' --init Inicializar configuração'));
22
- console.log(chalk.gray(' --show Mostrar configuração atual'));
23
- }
24
-
25
- } catch (error) {
26
- console.error(chalk.red('❌ Erro na configuração:'), error.message);
27
- process.exit(1);
28
- }
29
- };
30
-
31
- // Inicializar configuração
32
- async function initializeConfig(configPath) {
33
- console.log(chalk.blue('🔧 Inicializando configuração...'));
34
-
35
- const defaultConfig = {
36
- supabase: {
37
- projectId: 'your-project-id-here',
38
- url: 'https://your-project-id.supabase.co',
39
- serviceKey: 'your-service-key-here',
40
- anonKey: 'your-anon-key-here',
41
- databaseUrl: 'postgresql://postgres:[password]@db.your-project-id.supabase.co:5432/postgres',
42
- accessToken: 'your-personal-access-token-here'
43
- },
44
- backup: {
45
- includeFunctions: true,
46
- includeStorage: true,
47
- includeAuth: true,
48
- includeRealtime: true,
49
- outputDir: './backups'
50
- },
51
- restore: {
52
- cleanRestore: true,
53
- verifyAfterRestore: true
54
- }
55
- };
56
-
57
- try {
58
- await fs.writeFile(configPath, JSON.stringify(defaultConfig, null, 2));
59
- console.log(chalk.green('✅ Arquivo de configuração criado: .smoonbrc'));
60
- console.log(chalk.yellow('\n📝 Próximos passos:'));
61
- console.log(chalk.gray(' 1. Edite .smoonbrc com suas credenciais Supabase'));
62
- console.log(chalk.gray(' 2. Substitua os valores placeholder pelos reais'));
63
- console.log(chalk.gray(' 3. Execute: npx smoonb backup'));
64
- } catch (error) {
65
- throw new Error(`Falha ao criar arquivo de configuração: ${error.message}`);
66
- }
67
- }
68
-
69
- // Mostrar configuração atual
70
- async function showConfig(configPath) {
71
- console.log(chalk.blue('📋 Configuração atual:'));
72
-
73
- try {
74
- const configContent = await fs.readFile(configPath, 'utf8');
75
- const config = JSON.parse(configContent);
76
-
77
- console.log(chalk.green('✅ Arquivo de configuração encontrado'));
78
- console.log(chalk.gray(` - Localização: ${configPath}`));
79
-
80
- if (config.supabase?.projectId && config.supabase.projectId !== 'your-project-id-here') {
81
- console.log(chalk.gray(` - Project ID: ${config.supabase.projectId}`));
82
- } else {
83
- console.log(chalk.yellow(' - Project ID: Não configurado'));
84
- }
85
-
86
- if (config.supabase?.url && config.supabase.url !== 'https://your-project-id.supabase.co') {
87
- console.log(chalk.gray(` - Supabase URL: ${config.supabase.url}`));
88
- } else {
89
- console.log(chalk.yellow(' - Supabase URL: Não configurado'));
90
- }
91
-
92
- if (config.supabase?.serviceKey && config.supabase.serviceKey !== 'your-service-key-here') {
93
- console.log(chalk.gray(' - Service Key: Configurada'));
94
- } else {
95
- console.log(chalk.yellow(' - Service Key: Não configurada'));
96
- }
97
-
98
- if (config.supabase?.anonKey && config.supabase.anonKey !== 'your-anon-key-here') {
99
- console.log(chalk.gray(' - Anon Key: Configurada'));
100
- } else {
101
- console.log(chalk.yellow(' - Anon Key: Não configurada'));
102
- }
103
-
104
- if (config.supabase?.databaseUrl && !config.supabase.databaseUrl.includes('[password]')) {
105
- console.log(chalk.gray(' - Database URL: Configurada'));
106
- } else {
107
- console.log(chalk.yellow(' - Database URL: Não configurada'));
108
- }
109
-
110
- if (config.supabase?.accessToken && config.supabase.accessToken !== 'your-personal-access-token-here') {
111
- console.log(chalk.gray(' - Access Token: Configurado'));
112
- } else {
113
- console.log(chalk.yellow(' - Access Token: Não configurado (obrigatório para Management API)'));
114
- }
115
-
116
- console.log(chalk.blue('\n📊 Configurações de backup:'));
117
- console.log(chalk.gray(` - Output Dir: ${config.backup?.outputDir || './backups'}`));
118
- console.log(chalk.gray(` - Include Functions: ${config.backup?.includeFunctions || true}`));
119
- console.log(chalk.gray(` - Include Storage: ${config.backup?.includeStorage || true}`));
120
- console.log(chalk.gray(` - Include Auth: ${config.backup?.includeAuth || true}`));
121
- console.log(chalk.gray(` - Include Realtime: ${config.backup?.includeRealtime || true}`));
122
-
123
- console.log(chalk.blue('\n🔄 Configurações de restore:'));
124
- console.log(chalk.gray(` - Clean Restore: ${config.restore?.cleanRestore || true}`));
125
- console.log(chalk.gray(` - Verify After Restore: ${config.restore?.verifyAfterRestore || true}`));
126
-
127
- } catch (error) {
128
- if (error.code === 'ENOENT') {
129
- console.log(chalk.yellow('⚠️ Arquivo de configuração não encontrado'));
130
- console.log(chalk.gray(' - Use: npx smoonb config --init'));
131
- } else {
132
- throw new Error(`Falha ao ler arquivo de configuração: ${error.message}`);
133
- }
134
- }
1
+ const chalk = require('chalk');
2
+ const fs = require('fs').promises;
3
+ const path = require('path');
4
+ const { showBetaBanner } = require('../utils/banner');
5
+ const { t } = require('../i18n');
6
+
7
+ // Exportar FUNÇÃO em vez de objeto Command
8
+ module.exports = async (options) => {
9
+ showBetaBanner();
10
+
11
+ const getT = global.smoonbI18n?.t || t;
12
+ console.log(chalk.cyan.bold(`⚙️ ${getT('config.title')}\n`));
13
+
14
+ try {
15
+ const configPath = path.join(process.cwd(), '.smoonbrc');
16
+
17
+ if (options.init) {
18
+ await initializeConfig(configPath);
19
+ } else if (options.show) {
20
+ await showConfig(configPath);
21
+ } else {
22
+ console.log(chalk.yellow(`💡 ${getT('config.options')}`));
23
+ console.log(chalk.gray(` ${getT('config.initOption')}`));
24
+ console.log(chalk.gray(` ${getT('config.showOption')}`));
25
+ }
26
+
27
+ } catch (error) {
28
+ const getT = global.smoonbI18n?.t || t;
29
+ console.error(chalk.red(`❌ ${getT('config.error')}`), error.message);
30
+ process.exit(1);
31
+ }
32
+ };
33
+
34
+ // Inicializar configuração
35
+ async function initializeConfig(configPath) {
36
+ const getT = global.smoonbI18n?.t || t;
37
+ console.log(chalk.blue(`🔧 ${getT('config.init')}`));
38
+
39
+ const defaultConfig = {
40
+ supabase: {
41
+ projectId: 'your-project-id-here',
42
+ url: 'https://your-project-id.supabase.co',
43
+ serviceKey: 'your-service-key-here',
44
+ anonKey: 'your-anon-key-here',
45
+ databaseUrl: 'postgresql://postgres:[password]@db.your-project-id.supabase.co:5432/postgres',
46
+ accessToken: 'your-personal-access-token-here'
47
+ },
48
+ backup: {
49
+ includeFunctions: true,
50
+ includeStorage: true,
51
+ includeAuth: true,
52
+ includeRealtime: true,
53
+ outputDir: './backups'
54
+ },
55
+ restore: {
56
+ cleanRestore: true,
57
+ verifyAfterRestore: true
58
+ }
59
+ };
60
+
61
+ try {
62
+ const getT = global.smoonbI18n?.t || t;
63
+ await fs.writeFile(configPath, JSON.stringify(defaultConfig, null, 2));
64
+ console.log(chalk.green(`✅ ${getT('config.fileCreated', { path: '.smoonbrc' })}`));
65
+ console.log(chalk.yellow('\n📝 Próximos passos:'));
66
+ console.log(chalk.gray(' 1. Edite .smoonbrc com suas credenciais Supabase'));
67
+ console.log(chalk.gray(' 2. Substitua os valores placeholder pelos reais'));
68
+ console.log(chalk.gray(' 3. Execute: npx smoonb backup'));
69
+ } catch (error) {
70
+ const getT = global.smoonbI18n?.t || t;
71
+ throw new Error(`${getT('config.error')}: ${error.message}`);
72
+ }
73
+ }
74
+
75
+ // Mostrar configuração atual
76
+ async function showConfig(configPath) {
77
+ const getT = global.smoonbI18n?.t || t;
78
+ console.log(chalk.blue(`📋 ${getT('config.show')}`));
79
+
80
+ try {
81
+ const configContent = await fs.readFile(configPath, 'utf8');
82
+ const config = JSON.parse(configContent);
83
+
84
+ console.log(chalk.green('✅ Arquivo de configuração encontrado'));
85
+ console.log(chalk.gray(` - Localização: ${configPath}`));
86
+
87
+ if (config.supabase?.projectId && config.supabase.projectId !== 'your-project-id-here') {
88
+ console.log(chalk.gray(` - Project ID: ${config.supabase.projectId}`));
89
+ } else {
90
+ console.log(chalk.yellow(' - Project ID: Não configurado'));
91
+ }
92
+
93
+ if (config.supabase?.url && config.supabase.url !== 'https://your-project-id.supabase.co') {
94
+ console.log(chalk.gray(` - Supabase URL: ${config.supabase.url}`));
95
+ } else {
96
+ console.log(chalk.yellow(' - Supabase URL: Não configurado'));
97
+ }
98
+
99
+ if (config.supabase?.serviceKey && config.supabase.serviceKey !== 'your-service-key-here') {
100
+ console.log(chalk.gray(' - Service Key: Configurada'));
101
+ } else {
102
+ console.log(chalk.yellow(' - Service Key: Não configurada'));
103
+ }
104
+
105
+ if (config.supabase?.anonKey && config.supabase.anonKey !== 'your-anon-key-here') {
106
+ console.log(chalk.gray(' - Anon Key: Configurada'));
107
+ } else {
108
+ console.log(chalk.yellow(' - Anon Key: Não configurada'));
109
+ }
110
+
111
+ if (config.supabase?.databaseUrl && !config.supabase.databaseUrl.includes('[password]')) {
112
+ console.log(chalk.gray(' - Database URL: Configurada'));
113
+ } else {
114
+ console.log(chalk.yellow(' - Database URL: Não configurada'));
115
+ }
116
+
117
+ if (config.supabase?.accessToken && config.supabase.accessToken !== 'your-personal-access-token-here') {
118
+ console.log(chalk.gray(' - Access Token: Configurado'));
119
+ } else {
120
+ console.log(chalk.yellow(' - Access Token: Não configurado (obrigatório para Management API)'));
121
+ }
122
+
123
+ console.log(chalk.blue('\n📊 Configurações de backup:'));
124
+ console.log(chalk.gray(` - Output Dir: ${config.backup?.outputDir || './backups'}`));
125
+ console.log(chalk.gray(` - Include Functions: ${config.backup?.includeFunctions || true}`));
126
+ console.log(chalk.gray(` - Include Storage: ${config.backup?.includeStorage || true}`));
127
+ console.log(chalk.gray(` - Include Auth: ${config.backup?.includeAuth || true}`));
128
+ console.log(chalk.gray(` - Include Realtime: ${config.backup?.includeRealtime || true}`));
129
+
130
+ console.log(chalk.blue('\n🔄 Configurações de restore:'));
131
+ console.log(chalk.gray(` - Clean Restore: ${config.restore?.cleanRestore || true}`));
132
+ console.log(chalk.gray(` - Verify After Restore: ${config.restore?.verifyAfterRestore || true}`));
133
+
134
+ } catch (error) {
135
+ const getT = global.smoonbI18n?.t || t;
136
+ if (error.code === 'ENOENT') {
137
+ console.log(chalk.yellow(`⚠️ ${getT('config.fileNotFound', { path: configPath })}`));
138
+ console.log(chalk.gray(' - Use: npx smoonb config --init'));
139
+ } else {
140
+ throw new Error(`${getT('config.error')}: ${error.message}`);
141
+ }
142
+ }
135
143
  }
@@ -2,34 +2,38 @@ const chalk = require('chalk');
2
2
  const { ensureBin, runCommand } = require('../utils/cli');
3
3
  const { readConfig, validateFor } = require('../utils/config');
4
4
  const { showBetaBanner } = require('../utils/banner');
5
+ const { t } = require('../i18n');
5
6
 
6
7
  // Exportar FUNÇÃO em vez de objeto Command
7
8
  module.exports = async (_options) => {
8
9
  showBetaBanner();
9
10
 
10
11
  try {
12
+ const getT = global.smoonbI18n?.t || t;
13
+
11
14
  // Verificar se Supabase CLI está disponível
12
15
  const supabasePath = await ensureBin('supabase');
13
16
  if (!supabasePath) {
14
- console.error(chalk.red('❌ Supabase CLI não encontrado'));
15
- console.log(chalk.yellow('💡 Instale o Supabase CLI:'));
16
- console.log(chalk.yellow(' npm install -g supabase'));
17
- console.log(chalk.yellow(' ou visite: https://supabase.com/docs/guides/cli'));
17
+ console.error(chalk.red(`❌ ${getT('functions.cliNotFound')}`));
18
+ console.log(chalk.yellow(`💡 ${getT('functions.installCli')}`));
19
+ console.log(chalk.yellow(` ${getT('functions.installLink')}`));
20
+ console.log(chalk.yellow(` ${getT('functions.orVisit')}`));
18
21
  process.exit(1);
19
22
  }
20
23
 
21
- console.log(chalk.blue('⚡ Comandos disponíveis para Edge Functions:'));
22
- console.log(chalk.yellow('\n📋 Listar functions:'));
24
+ console.log(chalk.blue(`⚡ ${getT('functions.availableCommands')}`));
25
+ console.log(chalk.yellow(`\n📋 ${getT('functions.list')}`));
23
26
  console.log(chalk.gray(' npx smoonb functions list'));
24
- console.log(chalk.yellow('\n🚀 Deploy functions:'));
27
+ console.log(chalk.yellow(`\n🚀 ${getT('functions.deploy')}`));
25
28
  console.log(chalk.gray(' npx smoonb functions push'));
26
- console.log(chalk.yellow('\n📥 Pull functions (se disponível):'));
29
+ console.log(chalk.yellow(`\n📥 ${getT('functions.pull')}`));
27
30
  console.log(chalk.gray(' npx smoonb functions pull'));
28
- console.log(chalk.yellow('\n💡 Para mais opções, use o Supabase CLI diretamente:'));
31
+ console.log(chalk.yellow(`\n💡 ${getT('functions.moreOptions')}`));
29
32
  console.log(chalk.gray(' supabase functions --help'));
30
33
 
31
34
  } catch (error) {
32
- console.error(chalk.red(`❌ Erro: ${error.message}`));
35
+ const getT = global.smoonbI18n?.t || t;
36
+ console.error(chalk.red(`❌ ${getT('functions.error', { message: error.message })}`));
33
37
  process.exit(1);
34
38
  }
35
39
  };
@@ -5,6 +5,7 @@ const { ensureDir } = require('../utils/fsx');
5
5
  const { readEnvFile } = require('../utils/env');
6
6
  const { showBetaBanner } = require('../utils/banner');
7
7
  const { confirm } = require('../utils/prompt');
8
+ const { t } = require('../i18n');
8
9
 
9
10
  /**
10
11
  * Comando para importar arquivo .backup.gz e opcionalmente .storage.zip do Dashboard do Supabase
@@ -13,21 +14,22 @@ module.exports = async (options) => {
13
14
  showBetaBanner();
14
15
 
15
16
  try {
17
+ const getT = global.smoonbI18n?.t || t;
18
+
16
19
  // Termo de uso e aviso de risco
17
- console.log(chalk.yellow.bold('\n⚠️ TERMO DE USO E AVISO DE RISCO\n'));
18
- console.log(chalk.white('Ao prosseguir, você reconhece e concorda que o Supa Moonbase (smoonb) é fornecido "NO ESTADO EM QUE SE ENCONTRA" ("AS IS") e "CONFORME DISPONIBILIDADE", sem garantias de qualquer natureza—expressas, implícitas ou legais—incluindo, sem limitação, garantias de comercialização, adequação a um fim específico e não violação, na máxima extensão permitida pela lei aplicável. Operações de backup e restauração envolvem riscos, os ambientes variam amplamente e não é possível prever ou validar todas as configurações dos usuários. Você é o único responsável por validar seu ambiente, manter cópias independentes e verificar os resultados antes de utilizá-los em produção. O Supa Moonbase (smoonb) é construído com repositórios públicos, auditáveis e software livre, para auxiliar pessoas a simplificar seus fluxos, sem com isso criar qualquer garantia, promessa de suporte ou compromisso de nível de serviço.\n'));
19
- console.log(chalk.white('Limitação de responsabilidade (PT-BR) — Na máxima extensão permitida por lei, a Goalmoon, seus contribuidores e licenciadores não serão responsáveis por danos indiretos, incidentais, especiais, consequentes, exemplares ou punitivos (incluindo perda de dados, interrupção de negócios ou lucros cessantes) decorrentes do uso, incapacidade de uso, das operações de backup/restauração realizadas com, ou dos resultados gerados pelo Supa Moonbase (smoonb). Em qualquer hipótese, a responsabilidade total por todas as reivindicações relacionadas ao Supa Moonbase (smoonb) não excederá o valor pago por você pelo Supa Moonbase (smoonb) nos 12 meses anteriores ao evento. Nada neste aviso exclui ou limita responsabilidades onde tais limites sejam proibidos por lei, incluindo (conforme aplicável) dolo ou culpa grave.\n'));
20
- console.log(chalk.white('Observação para consumidores no Brasil (PT-BR) — Para consumidores brasileiros, este aviso não afasta direitos irrenunciáveis previstos no Código de Defesa do Consumidor (CDC); qualquer limitação aqui prevista só se aplica nos limites da lei e não impede a indenização obrigatória quando cabível.\n'));
20
+ console.log(chalk.yellow.bold(`\n⚠️ ${getT('disclaimer.title')}\n`));
21
+ console.log(chalk.white(`${getT('disclaimer.text')}\n`));
22
+ console.log(chalk.white(`${getT('disclaimer.limitation')}\n`));
21
23
 
22
- const termsAccepted = await confirm('Você aceita os Termos de Uso e o Aviso de Risco de Importação?', true);
24
+ const termsAccepted = await confirm(getT('disclaimer.acceptImport'), true);
23
25
  if (!termsAccepted) {
24
- console.log(chalk.red('🚫 Operação cancelada pelo usuário.'));
26
+ console.log(chalk.red(`🚫 ${getT('disclaimer.operationCancelled')}`));
25
27
  process.exit(1);
26
28
  }
27
-
29
+
28
30
  // Validar que o arquivo de backup foi fornecido
29
31
  if (!options.file) {
30
- console.error(chalk.red('❌ Arquivo de backup não fornecido'));
32
+ console.error(chalk.red(`❌ ${getT('import.fileRequired')}`));
31
33
  console.log(chalk.yellow('💡 Use: npx smoonb import --file <caminho-do-backup> [--storage <caminho-do-storage>]'));
32
34
  console.log(chalk.white(' Exemplo: npx smoonb import --file "C:\\Downloads\\db_cluster-04-03-2024@14-16-59.backup.gz"'));
33
35
  console.log(chalk.white(' Exemplo com storage: npx smoonb import --file "backup.backup.gz" --storage "meu-projeto.storage.zip"'));
@@ -40,13 +42,13 @@ module.exports = async (options) => {
40
42
  try {
41
43
  await fs.access(sourceFile);
42
44
  } catch {
43
- console.error(chalk.red(`❌ Arquivo de backup não encontrado: ${sourceFile}`));
45
+ console.error(chalk.red(`❌ ${getT('import.fileNotFound', { path: sourceFile })}`));
44
46
  process.exit(1);
45
47
  }
46
48
 
47
49
  // Verificar se é um arquivo .backup.gz ou .backup
48
50
  if (!sourceFile.endsWith('.backup.gz') && !sourceFile.endsWith('.backup')) {
49
- console.error(chalk.red('❌ Arquivo de backup deve ser .backup.gz ou .backup'));
51
+ console.error(chalk.red(`❌ ${getT('import.invalidFormat')}`));
50
52
  process.exit(1);
51
53
  }
52
54
 
@@ -58,13 +60,13 @@ module.exports = async (options) => {
58
60
  try {
59
61
  await fs.access(sourceStorageFile);
60
62
  } catch {
61
- console.error(chalk.red(`❌ Arquivo de storage não encontrado: ${sourceStorageFile}`));
63
+ console.error(chalk.red(`❌ ${getT('import.storageNotFound', { path: sourceStorageFile })}`));
62
64
  process.exit(1);
63
65
  }
64
66
 
65
67
  // Verificar se é um arquivo .storage.zip
66
68
  if (!sourceStorageFile.endsWith('.storage.zip')) {
67
- console.error(chalk.red('❌ Arquivo de storage deve ser .storage.zip'));
69
+ console.error(chalk.red(`❌ ${getT('import.storageInvalidFormat')}`));
68
70
  process.exit(1);
69
71
  }
70
72
  }
@@ -87,9 +89,9 @@ module.exports = async (options) => {
87
89
  const match = fileName.match(/db_cluster-(\d{2})-(\d{2})-(\d{4})@(\d{2})-(\d{2})-(\d{2})\.backup(\.gz)?/);
88
90
 
89
91
  if (!match) {
90
- console.error(chalk.red('❌ Nome do arquivo de backup não está no formato esperado do Dashboard'));
91
- console.log(chalk.yellow('💡 Formato esperado: db_cluster-DD-MM-YYYY@HH-MM-SS.backup.gz'));
92
- console.log(chalk.white(` Arquivo recebido: ${fileName}`));
92
+ console.error(chalk.red(`❌ ${getT('import.invalidFileName')}`));
93
+ console.log(chalk.yellow(`💡 ${getT('import.expectedFormat')}`));
94
+ console.log(chalk.white(` ${getT('import.fileReceived', { fileName })}`));
93
95
  process.exit(1);
94
96
  }
95
97
 
@@ -111,7 +113,7 @@ module.exports = async (options) => {
111
113
  const stats = await fs.stat(destFile);
112
114
  const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
113
115
 
114
- console.log(chalk.green(`✅ Arquivo de backup importado com sucesso!`));
116
+ console.log(chalk.green(`✅ ${getT('import.success')}`));
115
117
  console.log(chalk.blue(`📦 Backup: ${fileName} (${sizeMB} MB)`));
116
118
 
117
119
  // Copiar arquivo de storage se fornecido
@@ -123,15 +125,16 @@ module.exports = async (options) => {
123
125
  const storageStats = await fs.stat(destStorageFile);
124
126
  const storageSizeMB = (storageStats.size / (1024 * 1024)).toFixed(2);
125
127
 
126
- console.log(chalk.green(`✅ Arquivo de storage importado com sucesso!`));
128
+ console.log(chalk.green(`✅ ${getT('import.storageSuccess')}`));
127
129
  console.log(chalk.blue(`📦 Storage: ${storageFileName} (${storageSizeMB} MB)`));
128
130
  }
129
131
 
130
132
  console.log(chalk.blue(`📁 Localização: ${backupDir}`));
131
- console.log(chalk.cyan(`\n💡 Próximo passo: Execute 'npx smoonb restore' para restaurar este backup`));
133
+ console.log(chalk.cyan(`\n💡 ${getT('import.nextStep')}`));
132
134
 
133
135
  } catch (error) {
134
- console.error(chalk.red(`❌ Erro ao importar arquivo: ${error.message}`));
136
+ const getT = global.smoonbI18n?.t || t;
137
+ console.error(chalk.red(`❌ ${getT('error.generic')}: ${error.message}`));
135
138
  process.exit(1);
136
139
  }
137
140
  };
@@ -99,15 +99,17 @@ module.exports = async (options) => {
99
99
  showBetaBanner();
100
100
 
101
101
  try {
102
+ const { t } = require('../../i18n');
103
+ const getT = global.smoonbI18n?.t || t;
104
+
102
105
  // Termo de uso e aviso de risco
103
- console.log(chalk.yellow.bold('\n⚠️ TERMO DE USO E AVISO DE RISCO\n'));
104
- console.log(chalk.white('Ao prosseguir, você reconhece e concorda que o Supa Moonbase (smoonb) é fornecido "NO ESTADO EM QUE SE ENCONTRA" ("AS IS") e "CONFORME DISPONIBILIDADE", sem garantias de qualquer natureza—expressas, implícitas ou legais—incluindo, sem limitação, garantias de comercialização, adequação a um fim específico e não violação, na máxima extensão permitida pela lei aplicável. Operações de backup e restauração envolvem riscos, os ambientes variam amplamente e não é possível prever ou validar todas as configurações dos usuários. Você é o único responsável por validar seu ambiente, manter cópias independentes e verificar os resultados antes de utilizá-los em produção. O Supa Moonbase (smoonb) é construído com repositórios públicos, auditáveis e software livre, para auxiliar pessoas a simplificar seus fluxos, sem com isso criar qualquer garantia, promessa de suporte ou compromisso de nível de serviço.\n'));
105
- console.log(chalk.white('Limitação de responsabilidade (PT-BR) — Na máxima extensão permitida por lei, a Goalmoon, seus contribuidores e licenciadores não serão responsáveis por danos indiretos, incidentais, especiais, consequentes, exemplares ou punitivos (incluindo perda de dados, interrupção de negócios ou lucros cessantes) decorrentes do uso, incapacidade de uso, das operações de backup/restauração realizadas com, ou dos resultados gerados pelo Supa Moonbase (smoonb). Em qualquer hipótese, a responsabilidade total por todas as reivindicações relacionadas ao Supa Moonbase (smoonb) não excederá o valor pago por você pelo Supa Moonbase (smoonb) nos 12 meses anteriores ao evento. Nada neste aviso exclui ou limita responsabilidades onde tais limites sejam proibidos por lei, incluindo (conforme aplicável) dolo ou culpa grave.\n'));
106
- console.log(chalk.white('Observação para consumidores no Brasil (PT-BR) — Para consumidores brasileiros, este aviso não afasta direitos irrenunciáveis previstos no Código de Defesa do Consumidor (CDC); qualquer limitação aqui prevista só se aplica nos limites da lei e não impede a indenização obrigatória quando cabível.\n'));
106
+ console.log(chalk.yellow.bold(`\n⚠️ ${getT('disclaimer.title')}\n`));
107
+ console.log(chalk.white(`${getT('disclaimer.text')}\n`));
108
+ console.log(chalk.white(`${getT('disclaimer.limitation')}\n`));
107
109
 
108
- const termsAccepted = await confirm('Você aceita os Termos de Uso e o Aviso de Risco de Restauração?', true);
110
+ const termsAccepted = await confirm(getT('disclaimer.acceptRestore'), true);
109
111
  if (!termsAccepted) {
110
- console.log(chalk.red('🚫 Operação cancelada pelo usuário.'));
112
+ console.log(chalk.red(`🚫 ${getT('disclaimer.operationCancelled')}`));
111
113
  process.exit(1);
112
114
  }
113
115
 
@@ -115,13 +117,12 @@ module.exports = async (options) => {
115
117
  await step00DockerValidation();
116
118
 
117
119
  // Consentimento para leitura e escrita do .env.local
118
- console.log(chalk.yellow('\n⚠️ O smoonb irá ler e escrever o arquivo .env.local localmente.'));
119
- console.log(chalk.yellow(' Um backup automático do .env.local será criado antes de qualquer alteração.'));
120
- console.log(chalk.yellow(' Vamos mapear suas variáveis de ambiente para garantir que todas as chaves necessárias'));
121
- console.log(chalk.yellow(' estejam presentes e com os valores corretos do projeto de destino.'));
122
- const consentOk = await confirm('Você consente em prosseguir', true);
120
+ console.log(chalk.yellow(`\n⚠️ ${getT('consent.title')}`));
121
+ console.log(chalk.yellow(` ${getT('consent.backup')}`));
122
+ console.log(chalk.yellow(` ${getT('consent.mapping')}`));
123
+ const consentOk = await confirm(getT('consent.proceed'), true);
123
124
  if (!consentOk) {
124
- console.log(chalk.red('🚫 Operação cancelada pelo usuário.'));
125
+ console.log(chalk.red(`🚫 ${getT('disclaimer.operationCancelled')}`));
125
126
  process.exit(1);
126
127
  }
127
128