@mmmbuto/nexuscli 0.8.9 → 0.9.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.
@@ -1,29 +0,0 @@
1
- const express = require('express');
2
- const router = express.Router();
3
- const versionManager = require('../services/version-manager');
4
-
5
- /**
6
- * GET /api/v1/system/version
7
- * Returns version info and update status.
8
- */
9
- router.get('/version', async (req, res) => {
10
- try {
11
- const force = req.query.force === 'true';
12
- const info = await versionManager.checkUpdate(force);
13
- res.json(info);
14
- } catch (error) {
15
- // Fail safe
16
- res.json({
17
- current: versionManager.currentVersion,
18
- latest: null,
19
- updateAvailable: false,
20
- installMethod: 'unknown',
21
- updateCommand: '',
22
- status: 'error',
23
- error: 'internal error',
24
- checkedAt: new Date().toISOString()
25
- });
26
- }
27
- });
28
-
29
- module.exports = router;
@@ -1,170 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { execSync } = require('child_process');
4
- const https = require('https');
5
- const semver = require('semver');
6
- const NodeCache = require('node-cache');
7
- const packageJson = require('../../../package.json');
8
-
9
- // Cache update checks for 12 hours
10
- const cache = new NodeCache({ stdTTL: 43200 });
11
- const CACHE_KEY = 'version_check';
12
- const CACHE_TTL_OK = 43200; // 12h
13
- const CACHE_TTL_FAIL = 300; // 5m for unknown/error
14
-
15
- class VersionManager {
16
- constructor() {
17
- this.currentVersion = packageJson.version;
18
- this.pkgName = packageJson.name;
19
- this.projectRoot = path.resolve(__dirname, '../../../');
20
- }
21
-
22
- /**
23
- * Detects the installation method (git or npm).
24
- * @returns {'git' | 'npm' | 'unknown'}
25
- */
26
- detectInstallMethod() {
27
- // Check 1: .git directory existence
28
- const gitDir = path.join(this.projectRoot, '.git');
29
- if (fs.existsSync(gitDir)) {
30
- return 'git';
31
- }
32
-
33
- // Check 2: Inference from path (heuristic)
34
- // Global npm installs often reside in paths containing 'node_modules' but not '.git'
35
- if (__dirname.includes('node_modules')) {
36
- return 'npm';
37
- }
38
-
39
- return 'unknown';
40
- }
41
-
42
- /**
43
- * Fetches the latest version from NPM registry.
44
- * @returns {Promise<string|null>}
45
- */
46
- async fetchLatestNpmVersion() {
47
- const controller = new AbortController();
48
- const timer = setTimeout(() => controller.abort(), 3000); // wall-clock timeout
49
-
50
- try {
51
- const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(this.pkgName)}/latest`, {
52
- method: 'GET',
53
- headers: {
54
- 'Accept': 'application/json',
55
- 'User-Agent': 'NexusCLI-VersionManager'
56
- },
57
- signal: controller.signal
58
- });
59
-
60
- if (!res.ok) return null;
61
- const json = await res.json().catch(() => null);
62
- return json?.version || null;
63
- } catch {
64
- return null;
65
- } finally {
66
- clearTimeout(timer);
67
- }
68
- }
69
-
70
- /**
71
- * Checks for updates using Git.
72
- * @returns {{ status: 'ok'|'unknown'|'error', updateAvailable: boolean, latest: string|null, error: string|null }}
73
- */
74
- checkGitUpdate() {
75
- try {
76
- // 1. Verify git exists
77
- try {
78
- execSync('git --version', { stdio: 'ignore' });
79
- } catch (e) {
80
- return { status: 'error', updateAvailable: false, latest: null, error: 'git binary not found' };
81
- }
82
-
83
- // 2. Verify upstream exists
84
- let upstream;
85
- try {
86
- upstream = execSync('git rev-parse --abbrev-ref --symbolic-full-name @{u}', { cwd: this.projectRoot, encoding: 'utf8' }).trim();
87
- } catch (e) {
88
- return { status: 'unknown', updateAvailable: false, latest: null, error: 'no upstream configured' };
89
- }
90
-
91
- const [remoteName, ...branchParts] = upstream.split('/');
92
- const branchName = branchParts.join('/') || 'main';
93
-
94
- // 3. Fetch upstream (fail soft)
95
- try {
96
- execSync(`git fetch ${remoteName} ${branchName}`, { cwd: this.projectRoot, stdio: 'ignore', timeout: 5000 });
97
- } catch (e) {
98
- return { status: 'unknown', updateAvailable: false, latest: null, error: 'git fetch failed' };
99
- }
100
-
101
- // 4. Compare ahead/behind
102
- try {
103
- const counts = execSync(`git rev-list --left-right --count HEAD...${upstream}`, { cwd: this.projectRoot, encoding: 'utf8' }).trim();
104
- const [ahead, behind] = counts.split(/\s+/).map((n) => parseInt(n, 10));
105
-
106
- const updateAvailable = Number.isFinite(behind) && behind > 0;
107
- const latest = updateAvailable ? upstream : this.currentVersion;
108
-
109
- return { status: 'ok', updateAvailable, latest, error: null };
110
- } catch (e) {
111
- return { status: 'unknown', updateAvailable: false, latest: null, error: 'git compare failed' };
112
- }
113
- } catch (e) {
114
- return { status: 'error', updateAvailable: false, latest: null, error: 'git check failed' };
115
- }
116
- }
117
-
118
- /**
119
- * Main entry point to check for updates.
120
- * Uses cache.
121
- */
122
- async checkUpdate(force = false) {
123
- if (!force) {
124
- const cached = cache.get(CACHE_KEY);
125
- if (cached) return cached;
126
- }
127
-
128
- const installMethod = this.detectInstallMethod();
129
- let result = {
130
- current: this.currentVersion,
131
- latest: this.currentVersion,
132
- updateAvailable: false,
133
- installMethod,
134
- updateCommand: '',
135
- checkedAt: new Date().toISOString(),
136
- status: 'ok',
137
- error: null
138
- };
139
-
140
- if (installMethod === 'npm') {
141
- const latest = await this.fetchLatestNpmVersion();
142
- if (latest) {
143
- const latestCoerced = semver.coerce(latest);
144
- const currentCoerced = semver.coerce(this.currentVersion);
145
-
146
- result.latest = latest;
147
- result.updateAvailable = !!(latestCoerced && currentCoerced && semver.gt(latestCoerced, currentCoerced));
148
- result.updateCommand = `npm install -g ${this.pkgName}`;
149
- } else {
150
- result.status = 'unknown'; // Failed to fetch
151
- result.error = null;
152
- }
153
- } else if (installMethod === 'git') {
154
- const gitCheck = this.checkGitUpdate();
155
- result.status = gitCheck.status;
156
- result.error = gitCheck.error;
157
- result.updateAvailable = gitCheck.updateAvailable;
158
- result.latest = gitCheck.latest || this.currentVersion;
159
- result.updateCommand = gitCheck.status === 'ok' ? 'git pull' : '';
160
- } else {
161
- result.status = 'unknown';
162
- result.error = 'install method not detected';
163
- }
164
-
165
- cache.set(CACHE_KEY, result, result.status === 'ok' ? CACHE_TTL_OK : CACHE_TTL_FAIL);
166
- return result;
167
- }
168
- }
169
-
170
- module.exports = new VersionManager();