-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathcheck.ts
More file actions
93 lines (84 loc) · 2.97 KB
/
Copy pathcheck.ts
File metadata and controls
93 lines (84 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { execCommand, commandExists, parseVersion, compareVersions, cargoBinDir } from '../utils.js';
import { MIN_SYNC_CTL_VERSION } from '../constants.js';
import fs from 'fs';
import path from 'path';
import https from 'https';
export interface PrereqStatus {
status: 'ok' | 'missing' | 'outdated';
version?: string;
latestVersion?: string;
}
export function checkNodeVersion(): PrereqStatus {
const version = process.version;
const parsed = parseVersion(version);
if (!parsed || parsed.major < 18) {
return { status: 'outdated', version };
}
return { status: 'ok', version };
}
export async function checkCargo(): Promise<PrereqStatus> {
try {
const { stdout } = await execCommand('cargo --version');
const version = parseVersion(stdout);
return { status: 'ok', version: version ? `${version.major}.${version.minor}.${version.patch}` : stdout.trim() };
} catch {
const cargoPath = path.join(cargoBinDir(), 'cargo');
if (fs.existsSync(cargoPath)) {
return { status: 'ok', version: 'unknown' };
}
return { status: 'missing' };
}
}
/**
* Fetch the latest syncable-cli version from crates.io.
* Returns null if the lookup fails (network error, timeout, etc.)
*/
export async function getLatestCratesVersion(): Promise<string | null> {
return new Promise((resolve) => {
const req = https.get(
'https://crates.io/api/v1/crates/syncable-cli',
{ headers: { 'User-Agent': 'syncable-cli-skills-installer' }, timeout: 5_000 },
(res) => {
let data = '';
res.on('data', (chunk: Buffer) => { data += chunk; });
res.on('end', () => {
try {
const json = JSON.parse(data);
const version = json?.crate?.max_version || json?.versions?.[0]?.num;
resolve(version || null);
} catch {
resolve(null);
}
});
},
);
req.on('error', () => resolve(null));
req.on('timeout', () => { req.destroy(); resolve(null); });
});
}
export async function checkSyncCtl(): Promise<PrereqStatus> {
try {
const { stdout } = await execCommand('sync-ctl --version');
const version = parseVersion(stdout);
if (!version) {
return { status: 'ok', version: stdout.trim() };
}
const currentStr = `${version.major}.${version.minor}.${version.patch}`;
// First check: is it below the hard minimum?
const minVersion = parseVersion(MIN_SYNC_CTL_VERSION);
if (minVersion && compareVersions(version, minVersion) < 0) {
return { status: 'outdated', version: currentStr };
}
// Second check: is there a newer version on crates.io?
const latestStr = await getLatestCratesVersion();
if (latestStr) {
const latest = parseVersion(latestStr);
if (latest && compareVersions(version, latest) < 0) {
return { status: 'outdated', version: currentStr, latestVersion: latestStr };
}
}
return { status: 'ok', version: currentStr };
} catch {
return { status: 'missing' };
}
}