tova 0.4.0 → 0.4.1
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 +78 -55
- package/package.json +1 -1
- package/src/version.js +1 -1
package/bin/tova.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import { resolve, basename, dirname, join, relative } from 'path';
|
|
4
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, copyFileSync, rmSync, watch as fsWatch } from 'fs';
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, copyFileSync, rmSync, chmodSync, renameSync, watch as fsWatch } from 'fs';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
6
|
// Bun.hash used instead of crypto.createHash for faster hashing
|
|
7
7
|
import { Lexer } from '../src/lexer/lexer.js';
|
|
@@ -4397,6 +4397,17 @@ function detectInstallMethod() {
|
|
|
4397
4397
|
return 'npm';
|
|
4398
4398
|
}
|
|
4399
4399
|
|
|
4400
|
+
function compareSemver(a, b) {
|
|
4401
|
+
// Returns: -1 if a < b, 0 if a === b, 1 if a > b
|
|
4402
|
+
const pa = a.split('.').map(Number);
|
|
4403
|
+
const pb = b.split('.').map(Number);
|
|
4404
|
+
for (let i = 0; i < 3; i++) {
|
|
4405
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return -1;
|
|
4406
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return 1;
|
|
4407
|
+
}
|
|
4408
|
+
return 0;
|
|
4409
|
+
}
|
|
4410
|
+
|
|
4400
4411
|
async function upgradeCommand() {
|
|
4401
4412
|
console.log(`\n Current version: ${color.bold('Tova v' + VERSION)}\n`);
|
|
4402
4413
|
console.log(' Checking for updates...');
|
|
@@ -4404,102 +4415,95 @@ async function upgradeCommand() {
|
|
|
4404
4415
|
const installMethod = detectInstallMethod();
|
|
4405
4416
|
|
|
4406
4417
|
try {
|
|
4418
|
+
// Always check npm registry as the source of truth for latest version
|
|
4419
|
+
const res = await fetch('https://registry.npmjs.org/tova/latest');
|
|
4420
|
+
if (!res.ok) {
|
|
4421
|
+
console.error(color.red(' Could not reach the npm registry. Check your network connection.'));
|
|
4422
|
+
process.exit(1);
|
|
4423
|
+
}
|
|
4424
|
+
const data = await res.json();
|
|
4425
|
+
const latestVersion = data.version;
|
|
4426
|
+
|
|
4427
|
+
if (compareSemver(VERSION, latestVersion) >= 0) {
|
|
4428
|
+
console.log(` ${color.green('Already on the latest version')} (v${VERSION}).\n`);
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
console.log(` New version available: ${color.green('v' + latestVersion)}\n`);
|
|
4433
|
+
|
|
4407
4434
|
if (installMethod === 'binary') {
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4435
|
+
console.log(' Upgrading via binary...');
|
|
4436
|
+
|
|
4437
|
+
// Check GitHub releases for the matching binary
|
|
4438
|
+
const ghRes = await fetch('https://api.github.com/repos/tova-lang/tova-lang/releases/latest');
|
|
4439
|
+
let ghTag = null;
|
|
4440
|
+
if (ghRes.ok) {
|
|
4441
|
+
const ghData = await ghRes.json();
|
|
4442
|
+
const ghVersion = (ghData.tag_name || '').replace(/^v/, '');
|
|
4443
|
+
if (compareSemver(ghVersion, VERSION) > 0) {
|
|
4444
|
+
ghTag = ghData.tag_name;
|
|
4445
|
+
}
|
|
4413
4446
|
}
|
|
4414
|
-
const data = await res.json();
|
|
4415
|
-
const latestVersion = (data.tag_name || '').replace(/^v/, '');
|
|
4416
4447
|
|
|
4417
|
-
if (
|
|
4418
|
-
|
|
4448
|
+
if (!ghTag) {
|
|
4449
|
+
// No newer binary release available — fall back to npm install
|
|
4450
|
+
console.log(` ${color.dim('No binary release for v' + latestVersion + ' yet. Falling back to npm...')}\n`);
|
|
4451
|
+
await npmUpgrade(latestVersion);
|
|
4419
4452
|
return;
|
|
4420
4453
|
}
|
|
4421
4454
|
|
|
4422
|
-
console.log(` New version available: ${color.green('v' + latestVersion)}\n`);
|
|
4423
|
-
console.log(' Upgrading via binary...');
|
|
4424
|
-
|
|
4425
4455
|
// Detect platform
|
|
4426
4456
|
const platform = process.platform === 'darwin' ? 'darwin' : process.platform === 'linux' ? 'linux' : 'windows';
|
|
4427
4457
|
const arch = process.arch === 'arm64' ? 'arm64' : 'x64';
|
|
4428
4458
|
const assetName = `tova-${platform}-${arch}`;
|
|
4429
|
-
const downloadUrl = `https://github.com/tova-lang/tova-lang/releases/download/${
|
|
4459
|
+
const downloadUrl = `https://github.com/tova-lang/tova-lang/releases/download/${ghTag}/${assetName}.gz`;
|
|
4430
4460
|
|
|
4431
4461
|
const installDir = join(process.env.HOME || '', '.tova', 'bin');
|
|
4432
4462
|
const tmpPath = join(installDir, 'tova.download');
|
|
4433
4463
|
const binPath = join(installDir, 'tova');
|
|
4434
4464
|
|
|
4465
|
+
// Ensure install directory exists
|
|
4466
|
+
mkdirSync(installDir, { recursive: true });
|
|
4467
|
+
|
|
4435
4468
|
// Download compressed binary
|
|
4436
4469
|
const dlRes = await fetch(downloadUrl);
|
|
4437
4470
|
if (!dlRes.ok) {
|
|
4438
4471
|
// Fall back to uncompressed
|
|
4439
4472
|
const dlRes2 = await fetch(downloadUrl.replace('.gz', ''));
|
|
4440
4473
|
if (!dlRes2.ok) {
|
|
4441
|
-
console.
|
|
4442
|
-
|
|
4474
|
+
console.log(` ${color.dim('Binary download failed. Falling back to npm...')}\n`);
|
|
4475
|
+
await npmUpgrade(latestVersion);
|
|
4476
|
+
return;
|
|
4443
4477
|
}
|
|
4444
4478
|
writeFileSync(tmpPath, new Uint8Array(await dlRes2.arrayBuffer()));
|
|
4445
4479
|
} else {
|
|
4446
4480
|
// Decompress gzip
|
|
4447
4481
|
const compressed = new Uint8Array(await dlRes.arrayBuffer());
|
|
4448
|
-
const
|
|
4482
|
+
const { gunzipSync } = await import('zlib');
|
|
4483
|
+
const decompressed = gunzipSync(compressed);
|
|
4449
4484
|
writeFileSync(tmpPath, decompressed);
|
|
4450
4485
|
}
|
|
4451
4486
|
|
|
4452
4487
|
// Make executable
|
|
4453
|
-
const { chmodSync } = await import('fs');
|
|
4454
4488
|
chmodSync(tmpPath, 0o755);
|
|
4455
4489
|
|
|
4456
4490
|
// Verify the new binary works
|
|
4457
|
-
const
|
|
4458
|
-
|
|
4491
|
+
const { spawnSync } = await import('child_process');
|
|
4492
|
+
const verifyProc = spawnSync(tmpPath, ['--version'], { timeout: 10000 });
|
|
4493
|
+
if (verifyProc.status !== 0) {
|
|
4459
4494
|
rmSync(tmpPath, { force: true });
|
|
4460
|
-
console.error(color.red(' Downloaded binary verification failed.'));
|
|
4461
|
-
|
|
4495
|
+
console.error(color.red(' Downloaded binary verification failed. Falling back to npm...'));
|
|
4496
|
+
await npmUpgrade(latestVersion);
|
|
4497
|
+
return;
|
|
4462
4498
|
}
|
|
4463
4499
|
|
|
4464
4500
|
// Atomic rename
|
|
4465
|
-
const { renameSync } = await import('fs');
|
|
4466
4501
|
renameSync(tmpPath, binPath);
|
|
4467
4502
|
|
|
4468
4503
|
console.log(`\n ${color.green('✓')} Upgraded: v${VERSION} -> ${color.bold('v' + latestVersion)}\n`);
|
|
4469
4504
|
} else {
|
|
4470
|
-
// npm/bun install: check npm registry
|
|
4471
|
-
const res = await fetch('https://registry.npmjs.org/tova/latest');
|
|
4472
|
-
if (!res.ok) {
|
|
4473
|
-
console.error(color.red(' Could not reach the npm registry. Check your network connection.'));
|
|
4474
|
-
process.exit(1);
|
|
4475
|
-
}
|
|
4476
|
-
const data = await res.json();
|
|
4477
|
-
const latestVersion = data.version;
|
|
4478
|
-
|
|
4479
|
-
if (latestVersion === VERSION) {
|
|
4480
|
-
console.log(` ${color.green('Already on the latest version')} (v${VERSION}).\n`);
|
|
4481
|
-
return;
|
|
4482
|
-
}
|
|
4483
|
-
|
|
4484
|
-
console.log(` New version available: ${color.green('v' + latestVersion)}\n`);
|
|
4485
4505
|
console.log(' Upgrading...');
|
|
4486
|
-
|
|
4487
|
-
const pm = detectPackageManager();
|
|
4488
|
-
const installCmd = pm === 'bun' ? ['bun', ['add', '-g', 'tova@latest']]
|
|
4489
|
-
: pm === 'pnpm' ? ['pnpm', ['add', '-g', 'tova@latest']]
|
|
4490
|
-
: pm === 'yarn' ? ['yarn', ['global', 'add', 'tova@latest']]
|
|
4491
|
-
: ['npm', ['install', '-g', 'tova@latest']];
|
|
4492
|
-
|
|
4493
|
-
const proc = spawn(installCmd[0], installCmd[1], { stdio: 'inherit' });
|
|
4494
|
-
const exitCode = await new Promise(res => proc.on('close', res));
|
|
4495
|
-
|
|
4496
|
-
if (exitCode === 0) {
|
|
4497
|
-
console.log(`\n ${color.green('✓')} Upgraded to Tova v${latestVersion}.\n`);
|
|
4498
|
-
} else {
|
|
4499
|
-
console.error(color.red(`\n Upgrade failed (exit code ${exitCode}).`));
|
|
4500
|
-
console.error(` Try manually: ${installCmd[0]} ${installCmd[1].join(' ')}\n`);
|
|
4501
|
-
process.exit(1);
|
|
4502
|
-
}
|
|
4506
|
+
await npmUpgrade(latestVersion);
|
|
4503
4507
|
}
|
|
4504
4508
|
} catch (err) {
|
|
4505
4509
|
console.error(color.red(` Upgrade failed: ${err.message}`));
|
|
@@ -4512,6 +4516,25 @@ async function upgradeCommand() {
|
|
|
4512
4516
|
}
|
|
4513
4517
|
}
|
|
4514
4518
|
|
|
4519
|
+
async function npmUpgrade(latestVersion) {
|
|
4520
|
+
const pm = detectPackageManager();
|
|
4521
|
+
const installCmd = pm === 'bun' ? ['bun', ['add', '-g', 'tova@latest']]
|
|
4522
|
+
: pm === 'pnpm' ? ['pnpm', ['add', '-g', 'tova@latest']]
|
|
4523
|
+
: pm === 'yarn' ? ['yarn', ['global', 'add', 'tova@latest']]
|
|
4524
|
+
: ['npm', ['install', '-g', 'tova@latest']];
|
|
4525
|
+
|
|
4526
|
+
const proc = spawn(installCmd[0], installCmd[1], { stdio: 'inherit' });
|
|
4527
|
+
const exitCode = await new Promise(res => proc.on('close', res));
|
|
4528
|
+
|
|
4529
|
+
if (exitCode === 0) {
|
|
4530
|
+
console.log(`\n ${color.green('✓')} Upgraded to Tova v${latestVersion}.\n`);
|
|
4531
|
+
} else {
|
|
4532
|
+
console.error(color.red(`\n Upgrade failed (exit code ${exitCode}).`));
|
|
4533
|
+
console.error(` Try manually: ${installCmd[0]} ${installCmd[1].join(' ')}\n`);
|
|
4534
|
+
process.exit(1);
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4515
4538
|
function detectPackageManager() {
|
|
4516
4539
|
if (typeof Bun !== 'undefined') return 'bun';
|
|
4517
4540
|
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.1";
|