electrobun 0.0.19-beta.130 → 0.0.19-beta.132
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
package/src/cli/index.ts
CHANGED
|
@@ -306,54 +306,161 @@ async function ensureCEFDependencies(targetOS?: 'macos' | 'win' | 'linux', targe
|
|
|
306
306
|
const archName = platformArch;
|
|
307
307
|
const cefTarballUrl = `https://github.com/blackboardsh/electrobun/releases/download/${version}/electrobun-cef-${platformName}-${archName}.tar.gz`;
|
|
308
308
|
|
|
309
|
-
|
|
309
|
+
// Helper function to download with retry logic
|
|
310
|
+
async function downloadWithRetry(url: string, filePath: string, maxRetries = 3): Promise<void> {
|
|
311
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
312
|
+
try {
|
|
313
|
+
console.log(`Downloading CEF (attempt ${attempt}/${maxRetries}) from: ${url}`);
|
|
314
|
+
|
|
315
|
+
const response = await fetch(url);
|
|
316
|
+
if (!response.ok) {
|
|
317
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Get content length for progress tracking
|
|
321
|
+
const contentLength = response.headers.get('content-length');
|
|
322
|
+
const totalSize = contentLength ? parseInt(contentLength, 10) : 0;
|
|
323
|
+
|
|
324
|
+
// Create temp file with unique name to avoid conflicts
|
|
325
|
+
const fileStream = createWriteStream(filePath);
|
|
326
|
+
let downloadedSize = 0;
|
|
327
|
+
|
|
328
|
+
// Stream download with progress
|
|
329
|
+
if (response.body) {
|
|
330
|
+
const reader = response.body.getReader();
|
|
331
|
+
while (true) {
|
|
332
|
+
const { done, value } = await reader.read();
|
|
333
|
+
if (done) break;
|
|
334
|
+
|
|
335
|
+
const chunk = Buffer.from(value);
|
|
336
|
+
fileStream.write(chunk);
|
|
337
|
+
downloadedSize += chunk.length;
|
|
338
|
+
|
|
339
|
+
if (totalSize > 0) {
|
|
340
|
+
const percent = Math.round((downloadedSize / totalSize) * 100);
|
|
341
|
+
if (percent % 10 === 0) { // Log every 10%
|
|
342
|
+
console.log(` Progress: ${percent}% (${Math.round(downloadedSize / 1024 / 1024)}MB/${Math.round(totalSize / 1024 / 1024)}MB)`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
await new Promise((resolve, reject) => {
|
|
349
|
+
fileStream.end((error: any) => {
|
|
350
|
+
if (error) reject(error);
|
|
351
|
+
else resolve(void 0);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Verify file size if content-length was provided
|
|
356
|
+
if (totalSize > 0) {
|
|
357
|
+
const actualSize = (await import('fs')).statSync(filePath).size;
|
|
358
|
+
if (actualSize !== totalSize) {
|
|
359
|
+
throw new Error(`Downloaded file size mismatch: expected ${totalSize}, got ${actualSize}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
console.log(`✓ Download completed successfully (${Math.round(downloadedSize / 1024 / 1024)}MB)`);
|
|
364
|
+
return; // Success, exit retry loop
|
|
365
|
+
|
|
366
|
+
} catch (error: any) {
|
|
367
|
+
console.error(`Download attempt ${attempt} failed:`, error.message);
|
|
368
|
+
|
|
369
|
+
// Clean up partial download
|
|
370
|
+
if (existsSync(filePath)) {
|
|
371
|
+
unlinkSync(filePath);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (attempt === maxRetries) {
|
|
375
|
+
throw new Error(`Failed to download after ${maxRetries} attempts: ${error.message}`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Wait before retrying (exponential backoff)
|
|
379
|
+
const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s...
|
|
380
|
+
console.log(`Retrying in ${delay / 1000} seconds...`);
|
|
381
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
310
385
|
|
|
311
386
|
try {
|
|
312
|
-
//
|
|
313
|
-
const
|
|
314
|
-
if (!response.ok) {
|
|
315
|
-
throw new Error(`Failed to download CEF: ${response.status} ${response.statusText}`);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Create temp file
|
|
319
|
-
const tempFile = join(ELECTROBUN_DEP_PATH, `cef-${platformOS}-${platformArch}-temp.tar.gz`);
|
|
320
|
-
const fileStream = createWriteStream(tempFile);
|
|
387
|
+
// Create temp file with unique name
|
|
388
|
+
const tempFile = join(ELECTROBUN_DEP_PATH, `cef-${platformOS}-${platformArch}-${Date.now()}.tar.gz`);
|
|
321
389
|
|
|
322
|
-
//
|
|
323
|
-
|
|
324
|
-
const reader = response.body.getReader();
|
|
325
|
-
while (true) {
|
|
326
|
-
const { done, value } = await reader.read();
|
|
327
|
-
if (done) break;
|
|
328
|
-
fileStream.write(Buffer.from(value));
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
fileStream.end();
|
|
390
|
+
// Download with retry logic
|
|
391
|
+
await downloadWithRetry(cefTarballUrl, tempFile);
|
|
332
392
|
|
|
333
393
|
// Extract to platform-specific dist directory
|
|
334
394
|
console.log(`Extracting CEF dependencies for ${platformOS}-${platformArch}...`);
|
|
335
395
|
const platformDistPath = join(ELECTROBUN_DEP_PATH, `dist-${platformOS}-${platformArch}`);
|
|
336
396
|
mkdirSync(platformDistPath, { recursive: true });
|
|
337
397
|
|
|
338
|
-
//
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
398
|
+
// Helper function to validate tar file before extraction
|
|
399
|
+
async function validateTarFile(filePath: string): Promise<void> {
|
|
400
|
+
try {
|
|
401
|
+
// Quick validation - try to read the tar file header
|
|
402
|
+
const fd = await import('fs').then(fs => fs.promises.readFile(filePath));
|
|
403
|
+
|
|
404
|
+
// Check if it's a gzip file (magic bytes: 1f 8b)
|
|
405
|
+
if (fd.length < 2 || fd[0] !== 0x1f || fd[1] !== 0x8b) {
|
|
406
|
+
throw new Error('Invalid gzip header - file may be corrupted');
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log(`✓ Tar file validation passed (${Math.round(fd.length / 1024 / 1024)}MB)`);
|
|
410
|
+
} catch (error: any) {
|
|
411
|
+
throw new Error(`Tar file validation failed: ${error.message}`);
|
|
412
|
+
}
|
|
353
413
|
}
|
|
354
414
|
|
|
355
|
-
//
|
|
356
|
-
|
|
415
|
+
// Validate downloaded file before extraction
|
|
416
|
+
await validateTarFile(tempFile);
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
// Use Windows native tar.exe on Windows due to npm tar library issues
|
|
420
|
+
if (OS === 'win') {
|
|
421
|
+
console.log('Using Windows native tar.exe for reliable extraction...');
|
|
422
|
+
const relativeTempFile = relative(platformDistPath, tempFile);
|
|
423
|
+
execSync(`tar -xf "${relativeTempFile}"`, {
|
|
424
|
+
stdio: 'inherit',
|
|
425
|
+
cwd: platformDistPath
|
|
426
|
+
});
|
|
427
|
+
} else {
|
|
428
|
+
await tar.x({
|
|
429
|
+
file: tempFile,
|
|
430
|
+
cwd: platformDistPath,
|
|
431
|
+
preservePaths: false,
|
|
432
|
+
strip: 0,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
console.log(`✓ Extraction completed successfully`);
|
|
437
|
+
|
|
438
|
+
} catch (error: any) {
|
|
439
|
+
// Check if CEF directory was created despite the error (partial extraction)
|
|
440
|
+
const cefDir = join(platformDistPath, 'cef');
|
|
441
|
+
if (existsSync(cefDir)) {
|
|
442
|
+
const cefFiles = readdirSync(cefDir);
|
|
443
|
+
if (cefFiles.length > 0) {
|
|
444
|
+
console.warn(`⚠️ Extraction warning: ${error.message}`);
|
|
445
|
+
console.warn(` However, CEF files were extracted (${cefFiles.length} files found).`);
|
|
446
|
+
console.warn(` Proceeding with partial extraction - this usually works fine.`);
|
|
447
|
+
// Don't throw - continue with what we have
|
|
448
|
+
} else {
|
|
449
|
+
// No files extracted, this is a real failure
|
|
450
|
+
throw new Error(`Extraction failed (no files extracted): ${error.message}`);
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
// No CEF directory created, this is a real failure
|
|
454
|
+
throw new Error(`Extraction failed (no CEF directory created): ${error.message}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Clean up temp file only after successful extraction
|
|
459
|
+
try {
|
|
460
|
+
unlinkSync(tempFile);
|
|
461
|
+
} catch (cleanupError) {
|
|
462
|
+
console.warn('Could not clean up temp file:', cleanupError);
|
|
463
|
+
}
|
|
357
464
|
|
|
358
465
|
// Debug: List what was actually extracted for CEF
|
|
359
466
|
try {
|
|
@@ -370,11 +477,28 @@ async function ensureCEFDependencies(targetOS?: 'macos' | 'win' | 'linux', targe
|
|
|
370
477
|
console.error('Could not list CEF extracted files:', e);
|
|
371
478
|
}
|
|
372
479
|
|
|
373
|
-
console.log(
|
|
480
|
+
console.log(`✓ CEF dependencies for ${platformOS}-${platformArch} downloaded and cached successfully`);
|
|
374
481
|
|
|
375
482
|
} catch (error: any) {
|
|
376
483
|
console.error(`Failed to download CEF dependencies for ${platformOS}-${platformArch}:`, error.message);
|
|
377
|
-
|
|
484
|
+
|
|
485
|
+
// Provide helpful guidance based on the error
|
|
486
|
+
if (error.message.includes('corrupted download') || error.message.includes('zlib') || error.message.includes('unexpected end')) {
|
|
487
|
+
console.error('\n💡 This appears to be a download corruption issue. Suggestions:');
|
|
488
|
+
console.error(' • Check your internet connection stability');
|
|
489
|
+
console.error(' • Try running the command again (it will retry automatically)');
|
|
490
|
+
console.error(' • Clear the cache if the issue persists:');
|
|
491
|
+
console.error(` rm -rf "${ELECTROBUN_DEP_PATH}"`);
|
|
492
|
+
} else if (error.message.includes('HTTP 404') || error.message.includes('Not Found')) {
|
|
493
|
+
console.error('\n💡 The CEF release was not found. This could mean:');
|
|
494
|
+
console.error(' • The version specified doesn\'t have CEF binaries available');
|
|
495
|
+
console.error(' • You\'re using a development/unreleased version');
|
|
496
|
+
console.error(' • Try using a stable version instead');
|
|
497
|
+
} else {
|
|
498
|
+
console.error('\nPlease ensure you have an internet connection and the release exists.');
|
|
499
|
+
console.error(`If the problem persists, try clearing the cache: rm -rf "${ELECTROBUN_DEP_PATH}"`);
|
|
500
|
+
}
|
|
501
|
+
|
|
378
502
|
process.exit(1);
|
|
379
503
|
}
|
|
380
504
|
}
|
|
@@ -289,13 +289,17 @@ class MultitabBrowser {
|
|
|
289
289
|
|
|
290
290
|
// Hide all webviews
|
|
291
291
|
this.webviews.forEach((webview) => {
|
|
292
|
-
webview.classList.remove('active');
|
|
292
|
+
// webview.classList.remove('active');
|
|
293
|
+
webview.toggleHidden(true)
|
|
294
|
+
webview.togglePassthrough(true)
|
|
293
295
|
});
|
|
294
296
|
|
|
295
297
|
// Show the selected webview
|
|
296
298
|
const selectedWebview = this.webviews.get(tabId);
|
|
297
299
|
if (selectedWebview) {
|
|
298
300
|
selectedWebview.classList.add('active');
|
|
301
|
+
selectedWebview.toggleHidden(false)
|
|
302
|
+
selectedWebview.togglePassthrough(false)
|
|
299
303
|
}
|
|
300
304
|
|
|
301
305
|
this.activeTabId = tabId;
|