tova 0.4.1 → 0.4.3
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/bin/tova.js +109 -11
- package/package.json +1 -1
- package/src/version.js +1 -1
package/bin/tova.js
CHANGED
|
@@ -4408,6 +4408,55 @@ function compareSemver(a, b) {
|
|
|
4408
4408
|
return 0;
|
|
4409
4409
|
}
|
|
4410
4410
|
|
|
4411
|
+
function formatBytes(bytes) {
|
|
4412
|
+
if (bytes < 1024) return bytes + ' B';
|
|
4413
|
+
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
|
|
4414
|
+
return (bytes / 1048576).toFixed(1) + ' MB';
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4417
|
+
async function downloadWithProgress(url, destPath) {
|
|
4418
|
+
const res = await fetch(url);
|
|
4419
|
+
if (!res.ok) return null;
|
|
4420
|
+
|
|
4421
|
+
const contentLength = parseInt(res.headers.get('content-length'), 10) || 0;
|
|
4422
|
+
const reader = res.body.getReader();
|
|
4423
|
+
const chunks = [];
|
|
4424
|
+
let received = 0;
|
|
4425
|
+
|
|
4426
|
+
const barWidth = 20;
|
|
4427
|
+
|
|
4428
|
+
while (true) {
|
|
4429
|
+
const { done, value } = await reader.read();
|
|
4430
|
+
if (done) break;
|
|
4431
|
+
chunks.push(value);
|
|
4432
|
+
received += value.length;
|
|
4433
|
+
|
|
4434
|
+
if (isTTY) {
|
|
4435
|
+
if (contentLength > 0) {
|
|
4436
|
+
const pct = Math.min(100, Math.round((received / contentLength) * 100));
|
|
4437
|
+
const filled = Math.round((pct / 100) * barWidth);
|
|
4438
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(barWidth - filled);
|
|
4439
|
+
process.stdout.write(`\r Downloading... [${bar}] ${pct}% (${formatBytes(received)} / ${formatBytes(contentLength)})`);
|
|
4440
|
+
} else {
|
|
4441
|
+
process.stdout.write(`\r Downloading... ${formatBytes(received)}`);
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4444
|
+
}
|
|
4445
|
+
|
|
4446
|
+
if (isTTY) process.stdout.write('\n');
|
|
4447
|
+
|
|
4448
|
+
// Combine chunks into a single Uint8Array
|
|
4449
|
+
const result = new Uint8Array(received);
|
|
4450
|
+
let offset = 0;
|
|
4451
|
+
for (const chunk of chunks) {
|
|
4452
|
+
result.set(chunk, offset);
|
|
4453
|
+
offset += chunk.length;
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4456
|
+
writeFileSync(destPath, result);
|
|
4457
|
+
return { compressed: url.endsWith('.gz'), size: received };
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4411
4460
|
async function upgradeCommand() {
|
|
4412
4461
|
console.log(`\n Current version: ${color.bold('Tova v' + VERSION)}\n`);
|
|
4413
4462
|
console.log(' Checking for updates...');
|
|
@@ -4446,9 +4495,9 @@ async function upgradeCommand() {
|
|
|
4446
4495
|
}
|
|
4447
4496
|
|
|
4448
4497
|
if (!ghTag) {
|
|
4449
|
-
// No newer binary release
|
|
4450
|
-
console.log(` ${color.dim('No binary release for v' + latestVersion + ' yet.
|
|
4451
|
-
await
|
|
4498
|
+
// No newer binary release — install from npm tarball directly
|
|
4499
|
+
console.log(` ${color.dim('No binary release for v' + latestVersion + ' yet. Installing from npm...')}`);
|
|
4500
|
+
await npmTarballUpgrade(latestVersion);
|
|
4452
4501
|
return;
|
|
4453
4502
|
}
|
|
4454
4503
|
|
|
@@ -4465,20 +4514,22 @@ async function upgradeCommand() {
|
|
|
4465
4514
|
// Ensure install directory exists
|
|
4466
4515
|
mkdirSync(installDir, { recursive: true });
|
|
4467
4516
|
|
|
4468
|
-
// Download compressed binary
|
|
4469
|
-
|
|
4470
|
-
if (!
|
|
4517
|
+
// Download compressed binary with progress
|
|
4518
|
+
let dlResult = await downloadWithProgress(downloadUrl, tmpPath);
|
|
4519
|
+
if (!dlResult) {
|
|
4471
4520
|
// Fall back to uncompressed
|
|
4472
|
-
|
|
4473
|
-
if (!
|
|
4521
|
+
dlResult = await downloadWithProgress(downloadUrl.replace('.gz', ''), tmpPath);
|
|
4522
|
+
if (!dlResult) {
|
|
4474
4523
|
console.log(` ${color.dim('Binary download failed. Falling back to npm...')}\n`);
|
|
4475
4524
|
await npmUpgrade(latestVersion);
|
|
4476
4525
|
return;
|
|
4477
4526
|
}
|
|
4478
|
-
|
|
4479
|
-
|
|
4527
|
+
}
|
|
4528
|
+
|
|
4529
|
+
if (dlResult.compressed) {
|
|
4480
4530
|
// Decompress gzip
|
|
4481
|
-
|
|
4531
|
+
console.log(' Decompressing...');
|
|
4532
|
+
const compressed = readFileSync(tmpPath);
|
|
4482
4533
|
const { gunzipSync } = await import('zlib');
|
|
4483
4534
|
const decompressed = gunzipSync(compressed);
|
|
4484
4535
|
writeFileSync(tmpPath, decompressed);
|
|
@@ -4488,6 +4539,7 @@ async function upgradeCommand() {
|
|
|
4488
4539
|
chmodSync(tmpPath, 0o755);
|
|
4489
4540
|
|
|
4490
4541
|
// Verify the new binary works
|
|
4542
|
+
console.log(' Verifying binary...');
|
|
4491
4543
|
const { spawnSync } = await import('child_process');
|
|
4492
4544
|
const verifyProc = spawnSync(tmpPath, ['--version'], { timeout: 10000 });
|
|
4493
4545
|
if (verifyProc.status !== 0) {
|
|
@@ -4535,6 +4587,52 @@ async function npmUpgrade(latestVersion) {
|
|
|
4535
4587
|
}
|
|
4536
4588
|
}
|
|
4537
4589
|
|
|
4590
|
+
async function npmTarballUpgrade(latestVersion) {
|
|
4591
|
+
const installDir = join(process.env.HOME || '', '.tova');
|
|
4592
|
+
const binDir = join(installDir, 'bin');
|
|
4593
|
+
const libDir = join(installDir, 'lib');
|
|
4594
|
+
mkdirSync(libDir, { recursive: true });
|
|
4595
|
+
|
|
4596
|
+
// Download npm tarball
|
|
4597
|
+
const tarballUrl = `https://registry.npmjs.org/tova/-/tova-${latestVersion}.tgz`;
|
|
4598
|
+
const tarballPath = join(installDir, 'tova.tgz');
|
|
4599
|
+
|
|
4600
|
+
const dlResult = await downloadWithProgress(tarballUrl, tarballPath);
|
|
4601
|
+
if (!dlResult) {
|
|
4602
|
+
console.error(color.red(' Failed to download npm package. Try manually: bun add -g tova@latest'));
|
|
4603
|
+
process.exit(1);
|
|
4604
|
+
}
|
|
4605
|
+
|
|
4606
|
+
// Extract tarball into lib dir
|
|
4607
|
+
console.log(' Extracting...');
|
|
4608
|
+
const { spawnSync: spawnTar } = await import('child_process');
|
|
4609
|
+
rmSync(libDir, { recursive: true, force: true });
|
|
4610
|
+
mkdirSync(libDir, { recursive: true });
|
|
4611
|
+
const tarResult = spawnTar('tar', ['-xzf', tarballPath, '-C', libDir, '--strip-components=1'], { stdio: 'pipe' });
|
|
4612
|
+
rmSync(tarballPath, { force: true });
|
|
4613
|
+
if (tarResult.status !== 0) {
|
|
4614
|
+
console.error(color.red(' Failed to extract package. Try manually: bun add -g tova@latest'));
|
|
4615
|
+
process.exit(1);
|
|
4616
|
+
}
|
|
4617
|
+
|
|
4618
|
+
// Create wrapper script at ~/.tova/bin/tova
|
|
4619
|
+
const libBin = join(libDir, 'bin', 'tova.js');
|
|
4620
|
+
const wrapperScript = `#!/bin/sh\nexec bun "${libBin}" "$@"\n`;
|
|
4621
|
+
const binPath = join(binDir, 'tova');
|
|
4622
|
+
writeFileSync(binPath, wrapperScript);
|
|
4623
|
+
chmodSync(binPath, 0o755);
|
|
4624
|
+
|
|
4625
|
+
// Verify
|
|
4626
|
+
console.log(' Verifying...');
|
|
4627
|
+
const verifyProc = spawnTar(binPath, ['--version'], { timeout: 10000 });
|
|
4628
|
+
if (verifyProc.status !== 0) {
|
|
4629
|
+
console.error(color.red(' Verification failed. Try manually: bun add -g tova@latest'));
|
|
4630
|
+
process.exit(1);
|
|
4631
|
+
}
|
|
4632
|
+
|
|
4633
|
+
console.log(`\n ${color.green('✓')} Upgraded: v${VERSION} -> ${color.bold('v' + latestVersion)}\n`);
|
|
4634
|
+
}
|
|
4635
|
+
|
|
4538
4636
|
function detectPackageManager() {
|
|
4539
4637
|
if (typeof Bun !== 'undefined') return 'bun';
|
|
4540
4638
|
const ua = process.env.npm_config_user_agent || '';
|
package/package.json
CHANGED
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/embed-runtime.js — do not edit
|
|
2
|
-
export const VERSION = "0.4.
|
|
2
|
+
export const VERSION = "0.4.3";
|