inup 1.4.5 → 1.4.6
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/core/package-detector.js +2 -2
- package/dist/interactive-ui.js +2 -2
- package/dist/services/cache-manager.js +97 -0
- package/dist/services/index.js +1 -0
- package/dist/services/jsdelivr-registry.js +17 -48
- package/dist/services/npm-registry.js +14 -29
- package/dist/ui/input-handler.js +25 -24
- package/dist/ui/renderer/modal.js +3 -6
- package/dist/ui/renderer/package-list.js +38 -34
- package/dist/ui/state/filter-manager.js +8 -4
- package/dist/ui/state/state-manager.js +4 -4
- package/dist/ui/themes-colors.js +33 -0
- package/dist/ui/themes.js +3 -0
- package/dist/ui/utils/cursor.js +34 -2
- package/dist/ui/utils/index.js +2 -1
- package/dist/ui/utils/version.js +15 -3
- package/package.json +1 -1
|
@@ -38,6 +38,7 @@ const semver = __importStar(require("semver"));
|
|
|
38
38
|
const utils_1 = require("../utils");
|
|
39
39
|
const services_1 = require("../services");
|
|
40
40
|
const config_1 = require("../config");
|
|
41
|
+
const utils_2 = require("../ui/utils");
|
|
41
42
|
class PackageDetector {
|
|
42
43
|
constructor(options) {
|
|
43
44
|
this.packageJsonPath = null;
|
|
@@ -181,8 +182,7 @@ class PackageDetector {
|
|
|
181
182
|
version.startsWith('bitbucket:'));
|
|
182
183
|
}
|
|
183
184
|
showProgress(message) {
|
|
184
|
-
|
|
185
|
-
process.stdout.write(`\r${' '.repeat(80)}\r${message}`);
|
|
185
|
+
utils_2.ConsoleUtils.showProgress(message);
|
|
186
186
|
}
|
|
187
187
|
getOutdatedPackagesOnly(packages) {
|
|
188
188
|
return packages.filter((pkg) => pkg.isOutdated);
|
package/dist/interactive-ui.js
CHANGED
|
@@ -221,10 +221,10 @@ class InteractiveUI {
|
|
|
221
221
|
}
|
|
222
222
|
break;
|
|
223
223
|
case 'enter_filter_mode':
|
|
224
|
-
stateManager.enterFilterMode();
|
|
224
|
+
stateManager.enterFilterMode(action.preserveQuery);
|
|
225
225
|
break;
|
|
226
226
|
case 'exit_filter_mode':
|
|
227
|
-
stateManager.exitFilterMode();
|
|
227
|
+
stateManager.exitFilterMode(action.clearQuery);
|
|
228
228
|
break;
|
|
229
229
|
case 'filter_input':
|
|
230
230
|
stateManager.appendToFilterQuery(action.char);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packageCache = exports.CacheManager = void 0;
|
|
4
|
+
const config_1 = require("../config");
|
|
5
|
+
const persistent_cache_1 = require("./persistent-cache");
|
|
6
|
+
/**
|
|
7
|
+
* Unified cache manager that handles both in-memory and persistent disk caching.
|
|
8
|
+
* Consolidates caching logic used across registry services.
|
|
9
|
+
*/
|
|
10
|
+
class CacheManager {
|
|
11
|
+
constructor(ttl = config_1.CACHE_TTL) {
|
|
12
|
+
this.memoryCache = new Map();
|
|
13
|
+
this.ttl = ttl;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get cached data for a key, checking memory first, then disk.
|
|
17
|
+
* Returns null if not found or expired.
|
|
18
|
+
*/
|
|
19
|
+
get(key) {
|
|
20
|
+
// Check in-memory cache first (fastest)
|
|
21
|
+
const memoryCached = this.memoryCache.get(key);
|
|
22
|
+
if (memoryCached && Date.now() - memoryCached.timestamp < this.ttl) {
|
|
23
|
+
return memoryCached.data;
|
|
24
|
+
}
|
|
25
|
+
// Check persistent disk cache (survives restarts)
|
|
26
|
+
const diskCached = persistent_cache_1.persistentCache.get(key);
|
|
27
|
+
if (diskCached) {
|
|
28
|
+
// Populate in-memory cache for subsequent accesses
|
|
29
|
+
this.memoryCache.set(key, {
|
|
30
|
+
data: diskCached,
|
|
31
|
+
timestamp: Date.now(),
|
|
32
|
+
});
|
|
33
|
+
return diskCached;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Store data in both memory and disk cache.
|
|
39
|
+
*/
|
|
40
|
+
set(key, data) {
|
|
41
|
+
// Cache in memory
|
|
42
|
+
this.memoryCache.set(key, {
|
|
43
|
+
data,
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
});
|
|
46
|
+
// Cache to disk for persistence
|
|
47
|
+
persistent_cache_1.persistentCache.set(key, data);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get data from cache or fetch it using the provided fetcher function.
|
|
51
|
+
* This is the main entry point for cache-aside pattern.
|
|
52
|
+
*/
|
|
53
|
+
async getOrFetch(key, fetcher) {
|
|
54
|
+
// Try cache first
|
|
55
|
+
const cached = this.get(key);
|
|
56
|
+
if (cached) {
|
|
57
|
+
return cached;
|
|
58
|
+
}
|
|
59
|
+
// Fetch fresh data
|
|
60
|
+
const data = await fetcher();
|
|
61
|
+
if (data) {
|
|
62
|
+
this.set(key, data);
|
|
63
|
+
}
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Check if a key exists and is not expired in cache.
|
|
68
|
+
*/
|
|
69
|
+
has(key) {
|
|
70
|
+
return this.get(key) !== null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Clear in-memory cache (useful for testing).
|
|
74
|
+
*/
|
|
75
|
+
clear() {
|
|
76
|
+
this.memoryCache.clear();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Flush pending disk cache writes.
|
|
80
|
+
*/
|
|
81
|
+
flush() {
|
|
82
|
+
persistent_cache_1.persistentCache.flush();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get cache statistics.
|
|
86
|
+
*/
|
|
87
|
+
getStats() {
|
|
88
|
+
return {
|
|
89
|
+
memoryEntries: this.memoryCache.size,
|
|
90
|
+
diskStats: persistent_cache_1.persistentCache.getStats(),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.CacheManager = CacheManager;
|
|
95
|
+
// Default package version cache instance
|
|
96
|
+
exports.packageCache = new CacheManager();
|
|
97
|
+
//# sourceMappingURL=cache-manager.js.map
|
package/dist/services/index.js
CHANGED
|
@@ -22,4 +22,5 @@ __exportStar(require("./jsdelivr-registry"), exports);
|
|
|
22
22
|
__exportStar(require("./changelog-fetcher"), exports);
|
|
23
23
|
__exportStar(require("./version-checker"), exports);
|
|
24
24
|
__exportStar(require("./persistent-cache"), exports);
|
|
25
|
+
__exportStar(require("./cache-manager"), exports);
|
|
25
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -40,7 +40,8 @@ const undici_1 = require("undici");
|
|
|
40
40
|
const semver = __importStar(require("semver"));
|
|
41
41
|
const config_1 = require("../config");
|
|
42
42
|
const npm_registry_1 = require("./npm-registry");
|
|
43
|
-
const
|
|
43
|
+
const cache_manager_1 = require("./cache-manager");
|
|
44
|
+
const utils_1 = require("../ui/utils");
|
|
44
45
|
// Create a persistent connection pool for jsDelivr CDN with optimal settings
|
|
45
46
|
// This enables connection reuse and HTTP/1.1 keep-alive for blazing fast requests
|
|
46
47
|
const jsdelivrPool = new undici_1.Pool('https://cdn.jsdelivr.net', {
|
|
@@ -53,7 +54,6 @@ const jsdelivrPool = new undici_1.Pool('https://cdn.jsdelivr.net', {
|
|
|
53
54
|
// Batch configuration for progressive loading
|
|
54
55
|
const BATCH_SIZE = 5;
|
|
55
56
|
const BATCH_TIMEOUT_MS = 500;
|
|
56
|
-
const packageCache = new Map();
|
|
57
57
|
/**
|
|
58
58
|
* Fetches package.json from jsdelivr CDN for a specific version tag using undici pool.
|
|
59
59
|
* Uses connection pooling and keep-alive for maximum performance.
|
|
@@ -136,31 +136,15 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
136
136
|
// Process individual package fetch with immediate npm fallback on failure
|
|
137
137
|
const fetchPackageWithFallback = async (packageName) => {
|
|
138
138
|
const currentVersion = currentVersions?.get(packageName);
|
|
139
|
-
//
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
packageData.set(packageName,
|
|
139
|
+
// Use CacheManager for unified caching (memory + disk)
|
|
140
|
+
const cached = cache_manager_1.packageCache.get(packageName);
|
|
141
|
+
if (cached) {
|
|
142
|
+
packageData.set(packageName, cached);
|
|
143
143
|
completedCount++;
|
|
144
144
|
if (onProgress) {
|
|
145
145
|
onProgress(packageName, completedCount, total);
|
|
146
146
|
}
|
|
147
|
-
addToBatch(packageName,
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
// Try persistent disk cache (fast, survives restarts)
|
|
151
|
-
const diskCached = persistent_cache_1.persistentCache.get(packageName);
|
|
152
|
-
if (diskCached) {
|
|
153
|
-
// Also populate in-memory cache for subsequent accesses
|
|
154
|
-
packageCache.set(packageName, {
|
|
155
|
-
data: diskCached,
|
|
156
|
-
timestamp: Date.now(),
|
|
157
|
-
});
|
|
158
|
-
packageData.set(packageName, diskCached);
|
|
159
|
-
completedCount++;
|
|
160
|
-
if (onProgress) {
|
|
161
|
-
onProgress(packageName, completedCount, total);
|
|
162
|
-
}
|
|
163
|
-
addToBatch(packageName, diskCached);
|
|
147
|
+
addToBatch(packageName, cached);
|
|
164
148
|
return;
|
|
165
149
|
}
|
|
166
150
|
try {
|
|
@@ -185,13 +169,8 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
185
169
|
const result = npmData.get(packageName);
|
|
186
170
|
if (result) {
|
|
187
171
|
packageData.set(packageName, result);
|
|
188
|
-
//
|
|
189
|
-
packageCache.set(packageName,
|
|
190
|
-
data: result,
|
|
191
|
-
timestamp: Date.now(),
|
|
192
|
-
});
|
|
193
|
-
// Cache to disk for persistence
|
|
194
|
-
persistent_cache_1.persistentCache.set(packageName, result);
|
|
172
|
+
// CacheManager handles both memory and disk caching
|
|
173
|
+
cache_manager_1.packageCache.set(packageName, result);
|
|
195
174
|
addToBatch(packageName, result);
|
|
196
175
|
}
|
|
197
176
|
completedCount++;
|
|
@@ -210,13 +189,8 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
210
189
|
latestVersion,
|
|
211
190
|
allVersions: allVersions.sort(semver.rcompare),
|
|
212
191
|
};
|
|
213
|
-
// Cache the result
|
|
214
|
-
packageCache.set(packageName,
|
|
215
|
-
data: result,
|
|
216
|
-
timestamp: Date.now(),
|
|
217
|
-
});
|
|
218
|
-
// Cache to disk for persistence
|
|
219
|
-
persistent_cache_1.persistentCache.set(packageName, result);
|
|
192
|
+
// Cache the result using CacheManager (handles both memory and disk)
|
|
193
|
+
cache_manager_1.packageCache.set(packageName, result);
|
|
220
194
|
packageData.set(packageName, result);
|
|
221
195
|
completedCount++;
|
|
222
196
|
if (onProgress) {
|
|
@@ -231,13 +205,8 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
231
205
|
const result = npmData.get(packageName);
|
|
232
206
|
if (result) {
|
|
233
207
|
packageData.set(packageName, result);
|
|
234
|
-
//
|
|
235
|
-
packageCache.set(packageName,
|
|
236
|
-
data: result,
|
|
237
|
-
timestamp: Date.now(),
|
|
238
|
-
});
|
|
239
|
-
// Cache to disk for persistence
|
|
240
|
-
persistent_cache_1.persistentCache.set(packageName, result);
|
|
208
|
+
// CacheManager handles both memory and disk caching
|
|
209
|
+
cache_manager_1.packageCache.set(packageName, result);
|
|
241
210
|
addToBatch(packageName, result);
|
|
242
211
|
}
|
|
243
212
|
}
|
|
@@ -255,10 +224,10 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
255
224
|
// Flush any remaining batch items
|
|
256
225
|
flushBatch();
|
|
257
226
|
// Flush persistent cache to disk
|
|
258
|
-
|
|
259
|
-
// Clear the progress line
|
|
227
|
+
cache_manager_1.packageCache.flush();
|
|
228
|
+
// Clear the progress line if no custom progress handler
|
|
260
229
|
if (!onProgress) {
|
|
261
|
-
|
|
230
|
+
utils_1.ConsoleUtils.clearProgress();
|
|
262
231
|
}
|
|
263
232
|
return packageData;
|
|
264
233
|
}
|
|
@@ -266,7 +235,7 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
266
235
|
* Clear the package cache (useful for testing)
|
|
267
236
|
*/
|
|
268
237
|
function clearJsdelivrPackageCache() {
|
|
269
|
-
packageCache.clear();
|
|
238
|
+
cache_manager_1.packageCache.clear();
|
|
270
239
|
}
|
|
271
240
|
/**
|
|
272
241
|
* Close the jsDelivr connection pool (useful for graceful shutdown)
|
|
@@ -37,27 +37,17 @@ exports.getAllPackageData = getAllPackageData;
|
|
|
37
37
|
exports.clearPackageCache = clearPackageCache;
|
|
38
38
|
const semver = __importStar(require("semver"));
|
|
39
39
|
const config_1 = require("../config");
|
|
40
|
-
const
|
|
41
|
-
const
|
|
40
|
+
const cache_manager_1 = require("./cache-manager");
|
|
41
|
+
const utils_1 = require("../ui/utils");
|
|
42
42
|
/**
|
|
43
|
-
* Fetches package data from npm registry
|
|
44
|
-
*
|
|
43
|
+
* Fetches package data from npm registry.
|
|
44
|
+
* Uses the shared CacheManager for caching.
|
|
45
45
|
*/
|
|
46
46
|
async function fetchPackageFromRegistry(packageName) {
|
|
47
|
-
//
|
|
48
|
-
const
|
|
49
|
-
if (
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
// Check persistent disk cache (fast, survives restarts)
|
|
53
|
-
const diskCached = persistent_cache_1.persistentCache.get(packageName);
|
|
54
|
-
if (diskCached) {
|
|
55
|
-
// Also populate in-memory cache for subsequent accesses
|
|
56
|
-
packageCache.set(packageName, {
|
|
57
|
-
data: diskCached,
|
|
58
|
-
timestamp: Date.now(),
|
|
59
|
-
});
|
|
60
|
-
return diskCached;
|
|
47
|
+
// Use CacheManager for unified caching (memory + disk)
|
|
48
|
+
const cached = cache_manager_1.packageCache.get(packageName);
|
|
49
|
+
if (cached) {
|
|
50
|
+
return cached;
|
|
61
51
|
}
|
|
62
52
|
try {
|
|
63
53
|
const url = `${config_1.NPM_REGISTRY_URL}/${encodeURIComponent(packageName)}`;
|
|
@@ -89,13 +79,8 @@ async function fetchPackageFromRegistry(packageName) {
|
|
|
89
79
|
latestVersion,
|
|
90
80
|
allVersions,
|
|
91
81
|
};
|
|
92
|
-
// Cache the result
|
|
93
|
-
packageCache.set(packageName,
|
|
94
|
-
data: result,
|
|
95
|
-
timestamp: Date.now(),
|
|
96
|
-
});
|
|
97
|
-
// Cache to disk for persistence
|
|
98
|
-
persistent_cache_1.persistentCache.set(packageName, result);
|
|
82
|
+
// Cache the result using CacheManager (handles both memory and disk)
|
|
83
|
+
cache_manager_1.packageCache.set(packageName, result);
|
|
99
84
|
return result;
|
|
100
85
|
}
|
|
101
86
|
finally {
|
|
@@ -132,10 +117,10 @@ async function getAllPackageData(packageNames, onProgress) {
|
|
|
132
117
|
// Wait for all requests to complete
|
|
133
118
|
await Promise.all(allPromises);
|
|
134
119
|
// Flush persistent cache to disk
|
|
135
|
-
|
|
136
|
-
// Clear the progress line
|
|
120
|
+
cache_manager_1.packageCache.flush();
|
|
121
|
+
// Clear the progress line if no custom progress handler
|
|
137
122
|
if (!onProgress) {
|
|
138
|
-
|
|
123
|
+
utils_1.ConsoleUtils.clearProgress();
|
|
139
124
|
}
|
|
140
125
|
return packageData;
|
|
141
126
|
}
|
|
@@ -143,6 +128,6 @@ async function getAllPackageData(packageNames, onProgress) {
|
|
|
143
128
|
* Clear the package cache (useful for testing)
|
|
144
129
|
*/
|
|
145
130
|
function clearPackageCache() {
|
|
146
|
-
packageCache.clear();
|
|
131
|
+
cache_manager_1.packageCache.clear();
|
|
147
132
|
}
|
|
148
133
|
//# sourceMappingURL=npm-registry.js.map
|
package/dist/ui/input-handler.js
CHANGED
|
@@ -47,24 +47,34 @@ class InputHandler {
|
|
|
47
47
|
}
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
// Check for '/' character to
|
|
51
|
-
if (str === '/' && !uiState.showInfoModal
|
|
52
|
-
|
|
50
|
+
// Check for '/' character to handle filter mode (only when not in modal)
|
|
51
|
+
if (str === '/' && !uiState.showInfoModal) {
|
|
52
|
+
if (uiState.filterMode) {
|
|
53
|
+
// Apply search (exit filter mode but keep the filter)
|
|
54
|
+
this.onAction({ type: 'exit_filter_mode' });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Enter filter mode - preserve query if one exists (to edit it)
|
|
58
|
+
this.onAction({ type: 'enter_filter_mode', preserveQuery: !!uiState.filterQuery });
|
|
59
|
+
}
|
|
53
60
|
return;
|
|
54
61
|
}
|
|
55
62
|
// Handle filter mode input
|
|
56
63
|
if (uiState.filterMode) {
|
|
64
|
+
// Check for escape key (either via key.name or raw escape character)
|
|
65
|
+
if ((key && key.name === 'escape') || str === '\x1b') {
|
|
66
|
+
// Escape clears the filter and exits filter mode
|
|
67
|
+
this.onAction({ type: 'exit_filter_mode', clearQuery: true });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
57
70
|
if (key) {
|
|
58
71
|
switch (key.name) {
|
|
59
|
-
case 'escape':
|
|
60
|
-
this.onAction({ type: 'exit_filter_mode' });
|
|
61
|
-
return;
|
|
62
72
|
case 'backspace':
|
|
63
73
|
case 'delete':
|
|
64
74
|
this.onAction({ type: 'filter_backspace' });
|
|
65
75
|
return;
|
|
66
76
|
case 'return':
|
|
67
|
-
//
|
|
77
|
+
// Apply search (exit filter mode but keep the filter)
|
|
68
78
|
this.onAction({ type: 'exit_filter_mode' });
|
|
69
79
|
return;
|
|
70
80
|
case 'up':
|
|
@@ -116,10 +126,7 @@ class InputHandler {
|
|
|
116
126
|
// Check if any packages are selected
|
|
117
127
|
const selectedCount = states.filter((s) => s.selectedOption !== 'none').length;
|
|
118
128
|
if (selectedCount === 0) {
|
|
119
|
-
//
|
|
120
|
-
console.log('\n' +
|
|
121
|
-
'\x1b[33m⚠️ No packages selected. Press ↑/↓ to navigate and ←/→ to select versions, or ESC to exit.\x1b[39m');
|
|
122
|
-
// Re-render will happen automatically
|
|
129
|
+
// Do nothing if no packages selected
|
|
123
130
|
return;
|
|
124
131
|
}
|
|
125
132
|
this.cleanup();
|
|
@@ -164,13 +171,15 @@ class InputHandler {
|
|
|
164
171
|
this.onAction({ type: 'toggle_theme_modal' });
|
|
165
172
|
break;
|
|
166
173
|
case 'escape':
|
|
167
|
-
//
|
|
174
|
+
// Close modal if open
|
|
168
175
|
if (uiState.showInfoModal) {
|
|
169
176
|
this.onAction({ type: 'toggle_info_modal' });
|
|
170
177
|
}
|
|
171
|
-
else {
|
|
172
|
-
|
|
178
|
+
else if (uiState.filterQuery) {
|
|
179
|
+
// Clear filter if one is applied
|
|
180
|
+
this.onAction({ type: 'exit_filter_mode', clearQuery: true });
|
|
173
181
|
}
|
|
182
|
+
// Otherwise do nothing - Escape no longer exits the CLI
|
|
174
183
|
break;
|
|
175
184
|
}
|
|
176
185
|
}
|
|
@@ -178,11 +187,7 @@ class InputHandler {
|
|
|
178
187
|
this.onAction({ type: 'resize', height });
|
|
179
188
|
}
|
|
180
189
|
cleanup() {
|
|
181
|
-
utils_1.CursorUtils.
|
|
182
|
-
if (process.stdin.setRawMode) {
|
|
183
|
-
process.stdin.setRawMode(false);
|
|
184
|
-
}
|
|
185
|
-
process.stdin.pause();
|
|
190
|
+
utils_1.CursorUtils.cleanup();
|
|
186
191
|
}
|
|
187
192
|
}
|
|
188
193
|
exports.InputHandler = InputHandler;
|
|
@@ -219,11 +224,7 @@ class ConfirmationInputHandler {
|
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
226
|
cleanup() {
|
|
222
|
-
utils_1.CursorUtils.
|
|
223
|
-
if (process.stdin.setRawMode) {
|
|
224
|
-
process.stdin.setRawMode(false);
|
|
225
|
-
}
|
|
226
|
-
process.stdin.pause();
|
|
227
|
+
utils_1.CursorUtils.cleanup();
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
exports.ConfirmationInputHandler = ConfirmationInputHandler;
|
|
@@ -7,12 +7,9 @@ exports.renderPackageInfoLoading = renderPackageInfoLoading;
|
|
|
7
7
|
exports.renderPackageInfoModal = renderPackageInfoModal;
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const themes_colors_1 = require("../themes-colors");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function stripAnsi(str) {
|
|
14
|
-
return str.replace(/\u001b\[[0-9;]*m/g, '');
|
|
15
|
-
}
|
|
10
|
+
const utils_1 = require("../utils");
|
|
11
|
+
// Use shared ANSI stripping utility
|
|
12
|
+
const stripAnsi = utils_1.VersionUtils.stripAnsi;
|
|
16
13
|
/**
|
|
17
14
|
* Format a number for display (e.g., 1000000 -> "1M", 1000 -> "1K")
|
|
18
15
|
*/
|
|
@@ -213,6 +213,12 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
213
213
|
const padding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(filterDisplay));
|
|
214
214
|
output.push(filterDisplay + ' '.repeat(padding));
|
|
215
215
|
}
|
|
216
|
+
else if (filterQuery) {
|
|
217
|
+
// Show applied filter when not in filter mode but filter is active
|
|
218
|
+
const filterDisplay = ' ' + chalk_1.default.bold.white('Search: ') + (0, themes_colors_1.getThemeColor)('primary')(filterQuery) + (0, themes_colors_1.getThemeColor)('textSecondary')(' (press / to edit)');
|
|
219
|
+
const padding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(filterDisplay));
|
|
220
|
+
output.push(filterDisplay + ' '.repeat(padding));
|
|
221
|
+
}
|
|
216
222
|
else {
|
|
217
223
|
// Show instructions when not filtering
|
|
218
224
|
output.push(' ' +
|
|
@@ -249,51 +255,54 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
249
255
|
const endItem = Math.min(scrollOffset + maxVisibleItems, totalVisualItems);
|
|
250
256
|
let statusLine = '';
|
|
251
257
|
if (filterMode) {
|
|
252
|
-
// In filter mode, show ESC to
|
|
258
|
+
// In filter mode, show Enter to apply and ESC to clear
|
|
253
259
|
if (totalPackages === 0) {
|
|
254
260
|
statusLine = (0, themes_colors_1.getThemeColor)('warning')(`No matches found`) +
|
|
255
261
|
' ' +
|
|
256
|
-
|
|
257
|
-
(0, themes_colors_1.getThemeColor)('textSecondary')('Clear filter');
|
|
262
|
+
chalk_1.default.bold.white('Esc ') + chalk_1.default.gray('Clear');
|
|
258
263
|
}
|
|
259
264
|
else if (totalVisualItems > maxVisibleItems) {
|
|
260
|
-
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing ${chalk_1.default.white(startItem)}-${chalk_1.default.white(endItem)} of ${chalk_1.default.white(totalPackages)} matches
|
|
265
|
+
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing ${chalk_1.default.white(startItem)}-${chalk_1.default.white(endItem)} of ${chalk_1.default.white(totalPackages)} matches`) +
|
|
261
266
|
' ' +
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
chalk_1.default.bold.white('Enter ') + chalk_1.default.gray('Apply') +
|
|
268
|
+
' ' +
|
|
269
|
+
chalk_1.default.bold.white('Esc ') + chalk_1.default.gray('Clear');
|
|
264
270
|
}
|
|
265
271
|
else {
|
|
266
|
-
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing all ${chalk_1.default.white(totalPackages)} matches
|
|
272
|
+
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing all ${chalk_1.default.white(totalPackages)} matches`) +
|
|
273
|
+
' ' +
|
|
274
|
+
chalk_1.default.bold.white('Enter ') + chalk_1.default.gray('Apply') +
|
|
267
275
|
' ' +
|
|
268
|
-
|
|
269
|
-
(0, themes_colors_1.getThemeColor)('textSecondary')('Clear filter');
|
|
276
|
+
chalk_1.default.bold.white('Esc ') + chalk_1.default.gray('Clear');
|
|
270
277
|
}
|
|
271
278
|
}
|
|
272
279
|
else if (totalPackages < totalBeforeFilter) {
|
|
273
280
|
// Filter is applied but not in filter mode
|
|
274
281
|
if (totalVisualItems > maxVisibleItems) {
|
|
275
|
-
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing ${chalk_1.default.white(startItem)}-${chalk_1.default.white(endItem)} of ${chalk_1.default.white(totalPackages)} matches
|
|
282
|
+
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing ${chalk_1.default.white(startItem)}-${chalk_1.default.white(endItem)} of ${chalk_1.default.white(totalPackages)} matches`) +
|
|
283
|
+
' ' +
|
|
284
|
+
chalk_1.default.bold.white('D/P/O ') + chalk_1.default.gray('Filter') +
|
|
276
285
|
' ' +
|
|
277
|
-
|
|
278
|
-
(0, themes_colors_1.getThemeColor)('textSecondary')('Edit filter') +
|
|
286
|
+
chalk_1.default.bold.white('M ') + chalk_1.default.gray('Minor') +
|
|
279
287
|
' ' +
|
|
280
|
-
|
|
281
|
-
(0, themes_colors_1.getThemeColor)('textSecondary')('Confirm') +
|
|
288
|
+
chalk_1.default.bold.white('L ') + chalk_1.default.gray('All') +
|
|
282
289
|
' ' +
|
|
283
|
-
|
|
284
|
-
|
|
290
|
+
chalk_1.default.bold.white('U ') + chalk_1.default.gray('None') +
|
|
291
|
+
' ' +
|
|
292
|
+
chalk_1.default.bold.white('Esc ') + chalk_1.default.gray('Clear');
|
|
285
293
|
}
|
|
286
294
|
else {
|
|
287
|
-
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing all ${chalk_1.default.white(totalPackages)} matches
|
|
295
|
+
statusLine = (0, themes_colors_1.getThemeColor)('textSecondary')(`Showing all ${chalk_1.default.white(totalPackages)} matches`) +
|
|
296
|
+
' ' +
|
|
297
|
+
chalk_1.default.bold.white('D/P/O ') + chalk_1.default.gray('Filter') +
|
|
298
|
+
' ' +
|
|
299
|
+
chalk_1.default.bold.white('M ') + chalk_1.default.gray('Minor') +
|
|
288
300
|
' ' +
|
|
289
|
-
|
|
290
|
-
chalk_1.default.gray('Edit filter') +
|
|
301
|
+
chalk_1.default.bold.white('L ') + chalk_1.default.gray('All') +
|
|
291
302
|
' ' +
|
|
292
|
-
chalk_1.default.
|
|
293
|
-
chalk_1.default.gray('Confirm') +
|
|
303
|
+
chalk_1.default.bold.white('U ') + chalk_1.default.gray('None') +
|
|
294
304
|
' ' +
|
|
295
|
-
chalk_1.default.
|
|
296
|
-
chalk_1.default.gray('Cancel');
|
|
305
|
+
chalk_1.default.bold.white('Esc ') + chalk_1.default.gray('Clear');
|
|
297
306
|
}
|
|
298
307
|
}
|
|
299
308
|
else {
|
|
@@ -301,23 +310,18 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
301
310
|
if (totalVisualItems > maxVisibleItems) {
|
|
302
311
|
statusLine = chalk_1.default.gray(`Showing ${chalk_1.default.white(startItem)}-${chalk_1.default.white(endItem)} of ${chalk_1.default.white(totalPackages)} packages`) +
|
|
303
312
|
' ' +
|
|
304
|
-
chalk_1.default.
|
|
305
|
-
chalk_1.default.gray('Confirm') +
|
|
306
|
-
' ' +
|
|
307
|
-
chalk_1.default.gray('Esc ') +
|
|
308
|
-
chalk_1.default.gray('Cancel');
|
|
313
|
+
chalk_1.default.bold.white('Enter ') + chalk_1.default.gray('Confirm');
|
|
309
314
|
}
|
|
310
315
|
else {
|
|
311
316
|
statusLine = chalk_1.default.gray(`Showing all ${chalk_1.default.white(totalPackages)} packages`) +
|
|
312
317
|
' ' +
|
|
313
|
-
chalk_1.default.
|
|
314
|
-
chalk_1.default.gray('Confirm') +
|
|
315
|
-
' ' +
|
|
316
|
-
chalk_1.default.gray('Esc ') +
|
|
317
|
-
chalk_1.default.gray('Cancel');
|
|
318
|
+
chalk_1.default.bold.white('Enter ') + chalk_1.default.gray('Confirm');
|
|
318
319
|
}
|
|
319
320
|
}
|
|
320
|
-
|
|
321
|
+
// Pad status line to terminal width to clear any leftover characters
|
|
322
|
+
const statusLineFull = ' ' + statusLine;
|
|
323
|
+
const statusPadding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(statusLineFull));
|
|
324
|
+
output.push(statusLineFull + ' '.repeat(statusPadding));
|
|
321
325
|
output.push('');
|
|
322
326
|
// Render visible items
|
|
323
327
|
if (renderableItems && renderableItems.length > 0) {
|
|
@@ -21,13 +21,17 @@ class FilterManager {
|
|
|
21
21
|
getFilterQuery() {
|
|
22
22
|
return this.state.filterQuery;
|
|
23
23
|
}
|
|
24
|
-
enterFilterMode() {
|
|
24
|
+
enterFilterMode(preserveQuery = false) {
|
|
25
25
|
this.state.filterMode = true;
|
|
26
|
-
|
|
26
|
+
if (!preserveQuery) {
|
|
27
|
+
this.state.filterQuery = '';
|
|
28
|
+
}
|
|
27
29
|
}
|
|
28
|
-
exitFilterMode() {
|
|
30
|
+
exitFilterMode(clearQuery = false) {
|
|
29
31
|
this.state.filterMode = false;
|
|
30
|
-
|
|
32
|
+
if (clearQuery) {
|
|
33
|
+
this.state.filterQuery = '';
|
|
34
|
+
}
|
|
31
35
|
}
|
|
32
36
|
updateFilterQuery(query) {
|
|
33
37
|
this.state.filterQuery = query;
|
|
@@ -161,12 +161,12 @@ class StateManager {
|
|
|
161
161
|
this.renderState.forceFullRender = true;
|
|
162
162
|
}
|
|
163
163
|
// Filter delegation
|
|
164
|
-
enterFilterMode() {
|
|
165
|
-
this.filterManager.enterFilterMode();
|
|
164
|
+
enterFilterMode(preserveQuery = false) {
|
|
165
|
+
this.filterManager.enterFilterMode(preserveQuery);
|
|
166
166
|
// Use incremental render for search mode toggle (no blink)
|
|
167
167
|
}
|
|
168
|
-
exitFilterMode() {
|
|
169
|
-
this.filterManager.exitFilterMode();
|
|
168
|
+
exitFilterMode(clearQuery = false) {
|
|
169
|
+
this.filterManager.exitFilterMode(clearQuery);
|
|
170
170
|
this.navigationManager.setCurrentRow(0);
|
|
171
171
|
this.navigationManager.setScrollOffset(0);
|
|
172
172
|
// Use incremental render for search mode toggle (no blink)
|
package/dist/ui/themes-colors.js
CHANGED
|
@@ -89,6 +89,39 @@ const themeColorDefinitions = {
|
|
|
89
89
|
text: '#ABB2BF',
|
|
90
90
|
textSecondary: '#5C6370',
|
|
91
91
|
},
|
|
92
|
+
gruvbox: {
|
|
93
|
+
bg: '#282828',
|
|
94
|
+
primary: '#83A598',
|
|
95
|
+
secondary: '#D3869B',
|
|
96
|
+
success: '#B8BB26',
|
|
97
|
+
warning: '#FABD2F',
|
|
98
|
+
error: '#FB4934',
|
|
99
|
+
border: '#504945',
|
|
100
|
+
text: '#EBDBB2',
|
|
101
|
+
textSecondary: '#A89984',
|
|
102
|
+
},
|
|
103
|
+
solarized: {
|
|
104
|
+
bg: '#002B36',
|
|
105
|
+
primary: '#268BD2',
|
|
106
|
+
secondary: '#D33682',
|
|
107
|
+
success: '#859900',
|
|
108
|
+
warning: '#B58900',
|
|
109
|
+
error: '#DC322F',
|
|
110
|
+
border: '#073642',
|
|
111
|
+
text: '#839496',
|
|
112
|
+
textSecondary: '#657B83',
|
|
113
|
+
},
|
|
114
|
+
github: {
|
|
115
|
+
bg: '#0D1117',
|
|
116
|
+
primary: '#58A6FF',
|
|
117
|
+
secondary: '#BC8CFF',
|
|
118
|
+
success: '#3FB950',
|
|
119
|
+
warning: '#D29922',
|
|
120
|
+
error: '#F85149',
|
|
121
|
+
border: '#30363D',
|
|
122
|
+
text: '#C9D1D9',
|
|
123
|
+
textSecondary: '#8B949E',
|
|
124
|
+
},
|
|
92
125
|
};
|
|
93
126
|
// Helper to apply color - handles both hex and named colors
|
|
94
127
|
function applyColor(color, text) {
|
package/dist/ui/themes.js
CHANGED
|
@@ -13,6 +13,9 @@ const themesMetadata = {
|
|
|
13
13
|
monokai: 'Monokai',
|
|
14
14
|
tokyonight: 'Tokyo Night',
|
|
15
15
|
onedark: 'One Dark',
|
|
16
|
+
gruvbox: 'Gruvbox',
|
|
17
|
+
solarized: 'Solarized',
|
|
18
|
+
github: 'GitHub',
|
|
16
19
|
};
|
|
17
20
|
// Theme definitions
|
|
18
21
|
exports.themes = Object.entries(themesMetadata).reduce((acc, [key, name]) => {
|
package/dist/ui/utils/cursor.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Cursor utility functions
|
|
3
|
+
* Cursor and terminal utility functions
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CursorUtils = void 0;
|
|
6
|
+
exports.ConsoleUtils = exports.CursorUtils = void 0;
|
|
7
7
|
exports.CursorUtils = {
|
|
8
8
|
/**
|
|
9
9
|
* Hide the cursor in the terminal
|
|
@@ -29,5 +29,37 @@ exports.CursorUtils = {
|
|
|
29
29
|
clearToEndOfScreen() {
|
|
30
30
|
process.stdout.write('\x1b[J');
|
|
31
31
|
},
|
|
32
|
+
/**
|
|
33
|
+
* Clean up terminal state - restore cursor and disable raw mode.
|
|
34
|
+
* Used when exiting interactive mode.
|
|
35
|
+
*/
|
|
36
|
+
cleanup() {
|
|
37
|
+
exports.CursorUtils.show();
|
|
38
|
+
if (process.stdin.setRawMode) {
|
|
39
|
+
process.stdin.setRawMode(false);
|
|
40
|
+
}
|
|
41
|
+
process.stdin.pause();
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Console utilities for progress display and line clearing
|
|
46
|
+
*/
|
|
47
|
+
exports.ConsoleUtils = {
|
|
48
|
+
/**
|
|
49
|
+
* Default line width for clearing progress messages
|
|
50
|
+
*/
|
|
51
|
+
LINE_WIDTH: 80,
|
|
52
|
+
/**
|
|
53
|
+
* Show a progress message on the current line (overwrites previous content)
|
|
54
|
+
*/
|
|
55
|
+
showProgress(message) {
|
|
56
|
+
process.stdout.write(`\r${' '.repeat(exports.ConsoleUtils.LINE_WIDTH)}\r${message}`);
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Clear the current progress line
|
|
60
|
+
*/
|
|
61
|
+
clearProgress() {
|
|
62
|
+
process.stdout.write('\r' + ' '.repeat(exports.ConsoleUtils.LINE_WIDTH) + '\r');
|
|
63
|
+
},
|
|
32
64
|
};
|
|
33
65
|
//# sourceMappingURL=cursor.js.map
|
package/dist/ui/utils/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CursorUtils = exports.VersionUtils = void 0;
|
|
3
|
+
exports.ConsoleUtils = exports.CursorUtils = exports.VersionUtils = void 0;
|
|
4
4
|
var version_1 = require("./version");
|
|
5
5
|
Object.defineProperty(exports, "VersionUtils", { enumerable: true, get: function () { return version_1.VersionUtils; } });
|
|
6
6
|
var cursor_1 = require("./cursor");
|
|
7
7
|
Object.defineProperty(exports, "CursorUtils", { enumerable: true, get: function () { return cursor_1.CursorUtils; } });
|
|
8
|
+
Object.defineProperty(exports, "ConsoleUtils", { enumerable: true, get: function () { return cursor_1.ConsoleUtils; } });
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/ui/utils/version.js
CHANGED
|
@@ -5,6 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.VersionUtils = void 0;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
/**
|
|
9
|
+
* ANSI escape code pattern for stripping terminal colors
|
|
10
|
+
*/
|
|
11
|
+
const ANSI_PATTERN = /\u001b\[[0-9;]*m/g;
|
|
8
12
|
class VersionUtils {
|
|
9
13
|
static applyVersionPrefix(originalSpecifier, targetVersion) {
|
|
10
14
|
// Extract prefix from original specifier (^ or ~)
|
|
@@ -13,9 +17,17 @@ class VersionUtils {
|
|
|
13
17
|
// Return target version with same prefix
|
|
14
18
|
return prefix + targetVersion;
|
|
15
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Strip ANSI escape codes from a string
|
|
22
|
+
*/
|
|
23
|
+
static stripAnsi(str) {
|
|
24
|
+
return str.replace(ANSI_PATTERN, '');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the visual length of a string (excluding ANSI codes)
|
|
28
|
+
*/
|
|
16
29
|
static getVisualLength(str) {
|
|
17
|
-
|
|
18
|
-
return str.replace(/\u001b\[[0-9;]*m/g, '').length;
|
|
30
|
+
return VersionUtils.stripAnsi(str).length;
|
|
19
31
|
}
|
|
20
32
|
/**
|
|
21
33
|
* Truncate text with ellipsis in the middle if it exceeds maxLength
|
|
@@ -35,7 +47,7 @@ class VersionUtils {
|
|
|
35
47
|
const startLength = Math.ceil(availableLength / 2);
|
|
36
48
|
const endLength = Math.floor(availableLength / 2);
|
|
37
49
|
// Extract raw text without ANSI codes to calculate positions
|
|
38
|
-
const rawText =
|
|
50
|
+
const rawText = VersionUtils.stripAnsi(str);
|
|
39
51
|
const start = rawText.substring(0, startLength);
|
|
40
52
|
const end = rawText.substring(rawText.length - endLength);
|
|
41
53
|
return start + ellipsis + end;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inup",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "Interactive CLI tool for upgrading dependencies with ease. Auto-detects and works with npm, yarn, pnpm, and bun. Inspired by yarn upgrade-interactive. Supports monorepos, workspaces, and batch upgrades.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|