smoonb 0.0.68 → 0.0.70

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.68",
3
+ "version": "0.0.70",
4
4
  "description": "Complete Supabase backup and migration tool - EXPERIMENTAL VERSION - USE AT YOUR OWN RISK",
5
5
  "preferGlobal": false,
6
6
  "preventGlobalInstall": true,
@@ -100,6 +100,7 @@ module.exports = async ({ backupPath, targetProject }) => {
100
100
 
101
101
  // 3. Selecionar o primeiro arquivo .storage.zip encontrado
102
102
  const storageZipFile = path.join(backupPath, storageZipFiles[0]);
103
+ const storageZipBaseName = path.basename(storageZipFiles[0], '.storage.zip');
103
104
  console.log(chalk.white(` - Arquivo de storage encontrado: ${storageZipFiles[0]}`));
104
105
 
105
106
  // 4. Validar credenciais do projeto destino
@@ -149,44 +150,41 @@ module.exports = async ({ backupPath, targetProject }) => {
149
150
  const bucketDirs = [];
150
151
 
151
152
  // Verificar se a pasta raiz é o Project ID (antigo ou novo)
152
- // Se for, as subpastas são os buckets reais
153
+ // Se for, as subpastas são os buckets reais - NUNCA tratar a pasta raiz como bucket
153
154
  let rootDir = null;
154
155
  if (extractedContents.length === 1) {
155
156
  const firstItem = extractedContents[0];
156
157
  const firstItemPath = path.join(extractDir, firstItem);
157
158
  const firstItemStats = await fs.stat(firstItemPath);
158
-
159
+
159
160
  if (firstItemStats.isDirectory()) {
160
161
  // Verificar se o nome da pasta raiz corresponde ao Project ID antigo OU novo
161
- // Isso pode acontecer se a pasta raiz original era o Project ID antigo
162
- // e pode ou não ter sido renomeada para o Project ID novo pela função replaceProjectIdInExtractedFiles
163
- const isProjectId =
164
- (sourceProjectId && firstItem === sourceProjectId) ||
165
- (firstItem === targetProject.targetProjectId);
166
-
162
+ const matchesSourceProjectId = sourceProjectId && firstItem === sourceProjectId;
163
+ const matchesTargetProjectId = firstItem === targetProject.targetProjectId;
164
+ const matchesZipFileName = firstItem === storageZipBaseName;
165
+ const matchesProjectIdPattern = isLikelyProjectId(firstItem);
166
+
167
+ const isProjectId =
168
+ matchesSourceProjectId ||
169
+ matchesTargetProjectId ||
170
+ matchesZipFileName ||
171
+ matchesProjectIdPattern;
172
+
167
173
  if (isProjectId) {
168
- // Verificar se contém subpastas (buckets reais)
169
- const subContents = await fs.readdir(firstItemPath);
170
- const hasSubDirs = subContents.some(item => {
171
- const itemPath = path.join(firstItemPath, item);
172
- try {
173
- const stats = fs.statSync(itemPath);
174
- return stats.isDirectory();
175
- } catch {
176
- return false;
177
- }
178
- });
179
-
180
- if (hasSubDirs) {
181
- // A pasta raiz é um wrapper do Project ID - buscar buckets nas subpastas
182
- rootDir = firstItem;
183
- console.log(chalk.white(` - Detectada pasta raiz com Project ID: ${firstItem}`));
184
- console.log(chalk.white(` - Buscando buckets nas subpastas...`));
185
- }
174
+ // A pasta raiz é um wrapper do Project ID - SEMPRE buscar buckets nas subpastas
175
+ rootDir = firstItem;
176
+ const reasons = [];
177
+ if (matchesSourceProjectId) reasons.push('manifest');
178
+ if (matchesTargetProjectId) reasons.push('projeto destino');
179
+ if (matchesZipFileName) reasons.push('nome do arquivo ZIP');
180
+ if (matchesProjectIdPattern) reasons.push('formato de Project ID');
181
+ const reasonText = reasons.length ? ` (${reasons.join(', ')})` : '';
182
+ console.log(chalk.white(` - Detectada pasta raiz com Project ID: ${firstItem}${reasonText}`));
183
+ console.log(chalk.white(` - Buscando buckets nas subpastas...`));
186
184
  }
187
185
  }
188
186
  }
189
-
187
+
190
188
  if (rootDir) {
191
189
  // Estrutura com Project ID: project-id/bucket-name/...
192
190
  // Listar subpastas dentro da pasta do Project ID - essas são os buckets reais
@@ -203,6 +201,13 @@ module.exports = async ({ backupPath, targetProject }) => {
203
201
  });
204
202
  }
205
203
  }
204
+
205
+ // Se não encontrou buckets nas subpastas, avisar e retornar erro
206
+ if (bucketDirs.length === 0) {
207
+ console.log(chalk.red(` ❌ Erro: Nenhum bucket encontrado nas subpastas de ${rootDir}`));
208
+ console.log(chalk.red(` ❌ A pasta raiz é um Project ID e não deve ser tratada como bucket`));
209
+ return { success: false, buckets_count: 0 };
210
+ }
206
211
  } else {
207
212
  // Estrutura direta: bucket-name/...
208
213
  // As pastas raiz são os buckets
@@ -560,3 +565,12 @@ function getContentType(fileName) {
560
565
 
561
566
  return contentTypes[ext] || 'application/octet-stream';
562
567
  }
568
+
569
+ function isLikelyProjectId(name) {
570
+ if (!name || typeof name !== 'string') {
571
+ return false;
572
+ }
573
+
574
+ // Project IDs do Supabase são normalmente strings de 20 caracteres alfanuméricos minúsculos
575
+ return /^[a-z0-9]{20}$/.test(name);
576
+ }