minara 0.2.6 → 0.2.7
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/dist/index.js +10 -1
- package/dist/update-check.d.ts +5 -0
- package/dist/update-check.js +77 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createRequire } from 'node:module';
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { setRawJson } from './formatters.js';
|
|
6
|
+
import { checkForUpdate } from './update-check.js';
|
|
6
7
|
// Auth & Account
|
|
7
8
|
import { loginCommand } from './commands/login.js';
|
|
8
9
|
import { logoutCommand } from './commands/logout.js';
|
|
@@ -24,6 +25,8 @@ import { premiumCommand } from './commands/premium.js';
|
|
|
24
25
|
import { configCommand } from './commands/config.js';
|
|
25
26
|
const require = createRequire(import.meta.url);
|
|
26
27
|
const { version } = require('../package.json');
|
|
28
|
+
// Fire update check early (non-blocking); result printed after command completes
|
|
29
|
+
const updateCheckPromise = checkForUpdate(version);
|
|
27
30
|
const program = new Command();
|
|
28
31
|
program
|
|
29
32
|
.name('minara')
|
|
@@ -65,8 +68,14 @@ program.addCommand(configCommand);
|
|
|
65
68
|
program.action(() => {
|
|
66
69
|
program.outputHelp();
|
|
67
70
|
});
|
|
68
|
-
program.parseAsync(process.argv)
|
|
71
|
+
program.parseAsync(process.argv)
|
|
72
|
+
.catch((err) => {
|
|
69
73
|
const message = err instanceof Error ? err.message : String(err);
|
|
70
74
|
console.error(chalk.red('Error:'), message);
|
|
71
75
|
process.exit(1);
|
|
76
|
+
})
|
|
77
|
+
.finally(async () => {
|
|
78
|
+
const notice = await updateCheckPromise;
|
|
79
|
+
if (notice)
|
|
80
|
+
console.log(notice);
|
|
72
81
|
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
const PKG_NAME = 'minara';
|
|
6
|
+
const CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000; // 4 hours
|
|
7
|
+
const CACHE_DIR = join(homedir(), '.minara');
|
|
8
|
+
const CACHE_FILE = join(CACHE_DIR, 'update-check.json');
|
|
9
|
+
const FETCH_TIMEOUT_MS = 3000;
|
|
10
|
+
function readCache() {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function writeCache(data) {
|
|
19
|
+
try {
|
|
20
|
+
mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 });
|
|
21
|
+
writeFileSync(CACHE_FILE, JSON.stringify(data), { mode: 0o600 });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// best-effort
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function isNewer(remote, local) {
|
|
28
|
+
const r = remote.split('.').map(Number);
|
|
29
|
+
const l = local.split('.').map(Number);
|
|
30
|
+
for (let i = 0; i < 3; i++) {
|
|
31
|
+
if ((r[i] ?? 0) > (l[i] ?? 0))
|
|
32
|
+
return true;
|
|
33
|
+
if ((r[i] ?? 0) < (l[i] ?? 0))
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Non-blocking update check. Returns a formatted notice string if a newer
|
|
40
|
+
* version is available on npm, or `null` if up-to-date / check skipped.
|
|
41
|
+
*/
|
|
42
|
+
export async function checkForUpdate(currentVersion) {
|
|
43
|
+
try {
|
|
44
|
+
// Use cache to avoid hitting npm on every invocation
|
|
45
|
+
const cached = readCache();
|
|
46
|
+
if (cached && Date.now() - cached.checkedAt < CHECK_INTERVAL_MS) {
|
|
47
|
+
return isNewer(cached.latest, currentVersion)
|
|
48
|
+
? formatNotice(currentVersion, cached.latest)
|
|
49
|
+
: null;
|
|
50
|
+
}
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
53
|
+
const res = await fetch(`https://registry.npmjs.org/${PKG_NAME}/latest`, {
|
|
54
|
+
signal: controller.signal,
|
|
55
|
+
headers: { Accept: 'application/json' },
|
|
56
|
+
});
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
if (!res.ok)
|
|
59
|
+
return null;
|
|
60
|
+
const { version: latest } = (await res.json());
|
|
61
|
+
if (!latest)
|
|
62
|
+
return null;
|
|
63
|
+
writeCache({ latest, checkedAt: Date.now() });
|
|
64
|
+
return isNewer(latest, currentVersion)
|
|
65
|
+
? formatNotice(currentVersion, latest)
|
|
66
|
+
: null;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function formatNotice(current, latest) {
|
|
73
|
+
const line = ` Update available: ${chalk.dim(current)} → ${chalk.green.bold(latest)}`;
|
|
74
|
+
const cmd = ` Run ${chalk.cyan('npm i -g minara')} to update`;
|
|
75
|
+
const border = chalk.yellow('─'.repeat(48));
|
|
76
|
+
return `\n${border}\n${line}\n${cmd}\n${border}`;
|
|
77
|
+
}
|