rushangle-cli 0.1.3 → 0.1.4

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rushangle-cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "SkillHub CLI - 数智凯航技能市场命令行工具",
5
5
  "bin": {
6
6
  "rushangle": "./bin/rushangle.js"
package/src/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  const { Command } = require('commander');
2
2
  const pkg = require('../package.json');
3
+ const { checkUpdate } = require('./update-checker');
4
+
5
+ // 启动时异步检查更新(不阻塞命令执行)
6
+ checkUpdate();
3
7
 
4
8
  const program = new Command();
5
9
 
@@ -0,0 +1,107 @@
1
+ const https = require('https');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const chalk = require('chalk');
5
+
6
+ const CACHE_DIR = path.join(require('os').homedir(), '.rushangle');
7
+ const CACHE_FILE = path.join(CACHE_DIR, '.update-check');
8
+ const CHECK_INTERVAL = 1000 * 60 * 60 * 24; // 每 24 小时检查一次
9
+
10
+ function getCache() {
11
+ try {
12
+ if (fs.existsSync(CACHE_FILE)) {
13
+ return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));
14
+ }
15
+ } catch {}
16
+ return null;
17
+ }
18
+
19
+ function setCache(data) {
20
+ try {
21
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
22
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(data));
23
+ } catch {}
24
+ }
25
+
26
+ function npmLatest(pkgName) {
27
+ return new Promise((resolve, reject) => {
28
+ const req = https.get(
29
+ `https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`,
30
+ { timeout: 5000 },
31
+ (res) => {
32
+ let body = '';
33
+ res.on('data', (chunk) => (body += chunk));
34
+ res.on('end', () => {
35
+ try {
36
+ const data = JSON.parse(body);
37
+ resolve(data.version);
38
+ } catch {
39
+ reject(new Error('Invalid response'));
40
+ }
41
+ });
42
+ }
43
+ );
44
+ req.on('error', reject);
45
+ req.on('timeout', () => {
46
+ req.destroy();
47
+ reject(new Error('Timeout'));
48
+ });
49
+ });
50
+ }
51
+
52
+ async function checkUpdate() {
53
+ try {
54
+ // 检查缓存是否有效
55
+ const cache = getCache();
56
+ if (cache && (Date.now() - cache.checkedAt) < CHECK_INTERVAL) {
57
+ return; // 缓存未过期,跳过
58
+ }
59
+
60
+ const pkg = require('../package.json');
61
+ const latest = await npmLatest(pkg.name);
62
+
63
+ // 更新缓存
64
+ setCache({ checkedAt: Date.now(), latest });
65
+
66
+ // 版本对比:去掉 v 前缀,语义化版本逐段对比
67
+ const current = pkg.version.replace(/^v/, '');
68
+ const latestVer = latest.replace(/^v/, '');
69
+
70
+ if (current !== latestVer) {
71
+ const parts = {
72
+ cur: current.split('.').map(Number),
73
+ lat: latestVer.split('.').map(Number),
74
+ };
75
+
76
+ const level =
77
+ parts.lat[0] > parts.cur[0] ? 'major'
78
+ : parts.lat[1] > parts.cur[1] ? 'minor'
79
+ : 'patch';
80
+
81
+ console.log('');
82
+ console.log(
83
+ chalk.yellow('╔══════════════════════════════════════════════════════════╗')
84
+ );
85
+ console.log(
86
+ chalk.yellow('║ 新版可用!') +
87
+ chalk.white(` ${pkg.name} `) +
88
+ chalk.green(`v${latestVer}`) +
89
+ chalk.white(`(当前 v${current})`) +
90
+ chalk.yellow(' ║')
91
+ );
92
+ console.log(
93
+ chalk.yellow('║ 运行 ') +
94
+ chalk.cyan('npm update -g ' + pkg.name) +
95
+ chalk.yellow(' 更新到最新版本 ║')
96
+ );
97
+ console.log(
98
+ chalk.yellow('╚══════════════════════════════════════════════════════════╝')
99
+ );
100
+ console.log('');
101
+ }
102
+ } catch {
103
+ // 网络错误等静默跳过,不影响正常使用
104
+ }
105
+ }
106
+
107
+ module.exports = { checkUpdate };