abapgit-agent 1.8.5 → 1.8.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/bin/abapgit-agent +10 -3
- package/package.json +2 -1
- package/src/commands/import.js +73 -15
- package/src/commands/pull.js +27 -1
- package/src/commands/upgrade.js +456 -0
- package/src/config.js +57 -1
- package/src/utils/backgroundJobPoller.README.md +218 -0
- package/src/utils/backgroundJobPoller.js +251 -0
- package/src/utils/version-check.js +182 -1
|
@@ -3,8 +3,30 @@
|
|
|
3
3
|
*/
|
|
4
4
|
const pathModule = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
6
7
|
const https = require('https');
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Get cache directory for abapgit-agent
|
|
11
|
+
* Follows OS-specific conventions:
|
|
12
|
+
* - Windows: %LOCALAPPDATA%\abapgit-agent\cache
|
|
13
|
+
* - Linux/macOS: ~/.cache/abapgit-agent (respects XDG_CACHE_HOME)
|
|
14
|
+
* @returns {string} Cache directory path
|
|
15
|
+
*/
|
|
16
|
+
function getCacheDir() {
|
|
17
|
+
const homeDir = os.homedir();
|
|
18
|
+
|
|
19
|
+
// Windows: %LOCALAPPDATA%\abapgit-agent\cache
|
|
20
|
+
if (process.platform === 'win32') {
|
|
21
|
+
const localAppData = process.env.LOCALAPPDATA || pathModule.join(homeDir, 'AppData', 'Local');
|
|
22
|
+
return pathModule.join(localAppData, 'abapgit-agent', 'cache');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Linux/macOS: respect XDG_CACHE_HOME or use ~/.cache
|
|
26
|
+
const xdgCache = process.env.XDG_CACHE_HOME || pathModule.join(homeDir, '.cache');
|
|
27
|
+
return pathModule.join(xdgCache, 'abapgit-agent');
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
/**
|
|
9
31
|
* Get CLI version from package.json
|
|
10
32
|
* @returns {string} CLI version or '1.0.0' as default
|
|
@@ -74,7 +96,166 @@ async function checkCompatibility(config) {
|
|
|
74
96
|
}
|
|
75
97
|
}
|
|
76
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Get configured npm registry URL
|
|
101
|
+
* Respects user's npm config (e.g., corporate mirrors, regional mirrors)
|
|
102
|
+
* @returns {string} Registry URL
|
|
103
|
+
*/
|
|
104
|
+
function getNpmRegistry() {
|
|
105
|
+
try {
|
|
106
|
+
const { execSync } = require('child_process');
|
|
107
|
+
const registry = execSync('npm config get registry', {
|
|
108
|
+
encoding: 'utf8',
|
|
109
|
+
stdio: ['pipe', 'pipe', 'ignore'] // Suppress stderr
|
|
110
|
+
}).trim();
|
|
111
|
+
|
|
112
|
+
// Validate registry URL
|
|
113
|
+
if (registry && registry.startsWith('http')) {
|
|
114
|
+
return registry;
|
|
115
|
+
}
|
|
116
|
+
} catch (e) {
|
|
117
|
+
// Fall back to default if npm config fails
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Default npm registry
|
|
121
|
+
return 'https://registry.npmjs.org/';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get latest version from npm registry
|
|
126
|
+
* Respects user's configured npm registry (mirrors, corporate proxies, etc.)
|
|
127
|
+
* @returns {Promise<string|null>} Latest version or null on error
|
|
128
|
+
*/
|
|
129
|
+
async function getLatestNpmVersion() {
|
|
130
|
+
return new Promise((resolve) => {
|
|
131
|
+
try {
|
|
132
|
+
const registry = getNpmRegistry();
|
|
133
|
+
// Ensure registry ends with /
|
|
134
|
+
const baseUrl = registry.endsWith('/') ? registry : registry + '/';
|
|
135
|
+
const url = `${baseUrl}abapgit-agent/latest`;
|
|
136
|
+
|
|
137
|
+
https.get(url, (res) => {
|
|
138
|
+
let body = '';
|
|
139
|
+
res.on('data', chunk => body += chunk);
|
|
140
|
+
res.on('end', () => {
|
|
141
|
+
try {
|
|
142
|
+
const data = JSON.parse(body);
|
|
143
|
+
resolve(data.version || null);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
resolve(null);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}).on('error', () => resolve(null));
|
|
149
|
+
} catch (e) {
|
|
150
|
+
resolve(null);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Compare two semver versions
|
|
157
|
+
* @param {string} a - Version A (e.g., "1.9.0")
|
|
158
|
+
* @param {string} b - Version B (e.g., "1.8.6")
|
|
159
|
+
* @returns {number} 1 if a > b, -1 if a < b, 0 if equal
|
|
160
|
+
*/
|
|
161
|
+
function compareVersions(a, b) {
|
|
162
|
+
const aParts = a.split('.').map(Number);
|
|
163
|
+
const bParts = b.split('.').map(Number);
|
|
164
|
+
|
|
165
|
+
for (let i = 0; i < 3; i++) {
|
|
166
|
+
if (aParts[i] > bParts[i]) return 1;
|
|
167
|
+
if (aParts[i] < bParts[i]) return -1;
|
|
168
|
+
}
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Check for new version availability with daily caching
|
|
174
|
+
* Cache file location (OS-specific):
|
|
175
|
+
* - Linux/macOS: ~/.cache/abapgit-agent/version-check.json
|
|
176
|
+
* - Windows: %LOCALAPPDATA%\abapgit-agent\cache\version-check.json
|
|
177
|
+
* Format: { lastCheck: timestamp, latestVersion: "1.9.0" }
|
|
178
|
+
* @returns {Promise<object>} { hasNewVersion, latestVersion, currentVersion }
|
|
179
|
+
*/
|
|
180
|
+
async function checkForNewVersion() {
|
|
181
|
+
const cliVersion = getCliVersion();
|
|
182
|
+
const cacheFile = pathModule.join(getCacheDir(), 'version-check.json');
|
|
183
|
+
const now = Date.now();
|
|
184
|
+
const ONE_DAY = 24 * 60 * 60 * 1000;
|
|
185
|
+
|
|
186
|
+
// Read cache if exists and less than 24 hours old
|
|
187
|
+
if (fs.existsSync(cacheFile)) {
|
|
188
|
+
try {
|
|
189
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
190
|
+
if (now - cache.lastCheck < ONE_DAY && cache.latestVersion) {
|
|
191
|
+
// Use cached result
|
|
192
|
+
return {
|
|
193
|
+
hasNewVersion: compareVersions(cache.latestVersion, cliVersion) > 0,
|
|
194
|
+
latestVersion: cache.latestVersion,
|
|
195
|
+
currentVersion: cliVersion
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
} catch (e) {
|
|
199
|
+
// Invalid cache, continue to fetch
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Fetch latest version from npm
|
|
204
|
+
const latestVersion = await getLatestNpmVersion();
|
|
205
|
+
|
|
206
|
+
if (latestVersion) {
|
|
207
|
+
// Write cache
|
|
208
|
+
try {
|
|
209
|
+
const cacheDir = pathModule.dirname(cacheFile);
|
|
210
|
+
if (!fs.existsSync(cacheDir)) {
|
|
211
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
212
|
+
}
|
|
213
|
+
fs.writeFileSync(cacheFile, JSON.stringify({
|
|
214
|
+
lastCheck: now,
|
|
215
|
+
latestVersion: latestVersion
|
|
216
|
+
}));
|
|
217
|
+
} catch (e) {
|
|
218
|
+
// Ignore cache write errors
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
hasNewVersion: compareVersions(latestVersion, cliVersion) > 0,
|
|
223
|
+
latestVersion: latestVersion,
|
|
224
|
+
currentVersion: cliVersion
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Failed to fetch, return no update
|
|
229
|
+
return {
|
|
230
|
+
hasNewVersion: false,
|
|
231
|
+
latestVersion: null,
|
|
232
|
+
currentVersion: cliVersion
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Show new version reminder at end of command output
|
|
238
|
+
* Non-blocking, silent on error
|
|
239
|
+
*/
|
|
240
|
+
async function showNewVersionReminder() {
|
|
241
|
+
try {
|
|
242
|
+
const { hasNewVersion, latestVersion, currentVersion } = await checkForNewVersion();
|
|
243
|
+
|
|
244
|
+
if (hasNewVersion) {
|
|
245
|
+
console.log('');
|
|
246
|
+
console.log(`💡 New version available: ${latestVersion} (current: ${currentVersion})`);
|
|
247
|
+
console.log(` Run: abapgit-agent upgrade`);
|
|
248
|
+
}
|
|
249
|
+
} catch (e) {
|
|
250
|
+
// Silent - don't interrupt user's workflow
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
77
254
|
module.exports = {
|
|
78
255
|
getCliVersion,
|
|
79
|
-
checkCompatibility
|
|
256
|
+
checkCompatibility,
|
|
257
|
+
getLatestNpmVersion,
|
|
258
|
+
compareVersions,
|
|
259
|
+
checkForNewVersion,
|
|
260
|
+
showNewVersionReminder
|
|
80
261
|
};
|