inup 1.4.5 → 1.4.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/cli.js +6 -0
- package/dist/config/constants.js +4 -1
- package/dist/core/package-detector.js +45 -3
- 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 +351 -149
- 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/dist/utils/debug-logger.js +81 -0
- package/dist/utils/index.js +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ const path_1 = require("path");
|
|
|
11
11
|
const index_1 = require("./index");
|
|
12
12
|
const services_1 = require("./services");
|
|
13
13
|
const config_1 = require("./config");
|
|
14
|
+
const utils_1 = require("./utils");
|
|
14
15
|
const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '../package.json'), 'utf-8'));
|
|
15
16
|
const program = new commander_1.Command();
|
|
16
17
|
program
|
|
@@ -21,11 +22,15 @@ program
|
|
|
21
22
|
.option('-e, --exclude <patterns>', 'exclude paths matching regex patterns (comma-separated)', '')
|
|
22
23
|
.option('-i, --ignore <packages>', 'ignore packages (comma-separated, supports glob patterns like @babel/*)')
|
|
23
24
|
.option('--package-manager <name>', 'manually specify package manager (npm, yarn, pnpm, bun)')
|
|
25
|
+
.option('--debug', 'write verbose debug log to /tmp/inup-debug-YYYY-MM-DD.log')
|
|
24
26
|
.action(async (options) => {
|
|
25
27
|
console.log(chalk_1.default.bold.blue(`🚀 `) + chalk_1.default.bold.red(`i`) + chalk_1.default.bold.yellow(`n`) + chalk_1.default.bold.blue(`u`) + chalk_1.default.bold.magenta(`p`) + `\n`);
|
|
26
28
|
// Check for updates in the background (non-blocking)
|
|
27
29
|
const updateCheckPromise = (0, services_1.checkForUpdateAsync)('inup', packageJson.version);
|
|
28
30
|
const cwd = (0, path_1.resolve)(options.dir);
|
|
31
|
+
if (options.debug || process.env.INUP_DEBUG === '1') {
|
|
32
|
+
(0, utils_1.enableDebugLogging)();
|
|
33
|
+
}
|
|
29
34
|
// Load project config from .inuprc
|
|
30
35
|
const projectConfig = (0, config_1.loadProjectConfig)(cwd);
|
|
31
36
|
// Merge CLI exclude patterns with config
|
|
@@ -60,6 +65,7 @@ program
|
|
|
60
65
|
excludePatterns,
|
|
61
66
|
ignorePackages,
|
|
62
67
|
packageManager,
|
|
68
|
+
debug: options.debug || process.env.INUP_DEBUG === '1',
|
|
63
69
|
});
|
|
64
70
|
await upgrader.run();
|
|
65
71
|
// After the main flow completes, check if there's an update available
|
package/dist/config/constants.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_REGISTRY = exports.REQUEST_TIMEOUT = exports.CACHE_TTL = exports.MAX_CONCURRENT_REQUESTS = exports.JSDELIVR_CDN_URL = exports.NPM_REGISTRY_URL = exports.PACKAGE_NAME = void 0;
|
|
3
|
+
exports.DEFAULT_REGISTRY = exports.JSDELIVR_POOL_TIMEOUT = exports.JSDELIVR_RETRY_DELAYS = exports.JSDELIVR_RETRY_TIMEOUTS = exports.REQUEST_TIMEOUT = exports.CACHE_TTL = exports.MAX_CONCURRENT_REQUESTS = exports.JSDELIVR_CDN_URL = exports.NPM_REGISTRY_URL = exports.PACKAGE_NAME = void 0;
|
|
4
4
|
exports.PACKAGE_NAME = 'inup';
|
|
5
5
|
exports.NPM_REGISTRY_URL = 'https://registry.npmjs.org';
|
|
6
6
|
exports.JSDELIVR_CDN_URL = 'https://cdn.jsdelivr.net/npm';
|
|
7
7
|
exports.MAX_CONCURRENT_REQUESTS = 150;
|
|
8
8
|
exports.CACHE_TTL = 5 * 60 * 1000; // 5 minutes in milliseconds
|
|
9
9
|
exports.REQUEST_TIMEOUT = 60000; // 60 seconds in milliseconds
|
|
10
|
+
exports.JSDELIVR_RETRY_TIMEOUTS = [2000, 3500]; // short retry budget to keep fallback fast
|
|
11
|
+
exports.JSDELIVR_RETRY_DELAYS = [150]; // tiny backoff between jsDelivr retries in ms
|
|
12
|
+
exports.JSDELIVR_POOL_TIMEOUT = 60000; // keep-alive/connect lifecycle should be looser than per-request timeouts
|
|
10
13
|
exports.DEFAULT_REGISTRY = 'jsdelivr';
|
|
11
14
|
//# sourceMappingURL=constants.js.map
|
|
@@ -38,6 +38,8 @@ 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");
|
|
42
|
+
const utils_3 = require("../utils");
|
|
41
43
|
class PackageDetector {
|
|
42
44
|
constructor(options) {
|
|
43
45
|
this.packageJsonPath = null;
|
|
@@ -58,27 +60,46 @@ class PackageDetector {
|
|
|
58
60
|
throw new Error('No package.json found in current directory');
|
|
59
61
|
}
|
|
60
62
|
const packages = [];
|
|
63
|
+
const t0 = Date.now();
|
|
64
|
+
utils_3.debugLog.info('PackageDetector', `Starting scan in ${this.cwd}`);
|
|
61
65
|
// Always check all package.json files recursively with timeout protection
|
|
62
66
|
this.showProgress('🔍 Scanning repository for package.json files...');
|
|
67
|
+
const tScan = Date.now();
|
|
63
68
|
const allPackageJsonFiles = this.findPackageJsonFilesWithTimeout(30000); // 30 second timeout
|
|
69
|
+
utils_3.debugLog.perf('PackageDetector', `file scan (${allPackageJsonFiles.length} files)`, tScan, {
|
|
70
|
+
files: allPackageJsonFiles,
|
|
71
|
+
});
|
|
64
72
|
this.showProgress(`🔍 Found ${allPackageJsonFiles.length} package.json file${allPackageJsonFiles.length === 1 ? '' : 's'}`);
|
|
65
73
|
// Step 2: Collect all dependencies from package.json files (parallelized)
|
|
66
74
|
this.showProgress('🔍 Reading dependencies from package.json files...');
|
|
75
|
+
const tDeps = Date.now();
|
|
67
76
|
const allDepsRaw = await (0, utils_1.collectAllDependenciesAsync)(allPackageJsonFiles, {
|
|
68
77
|
includePeerDeps: true,
|
|
69
78
|
includeOptionalDeps: true,
|
|
70
79
|
});
|
|
80
|
+
utils_3.debugLog.perf('PackageDetector', `dependency collection (${allDepsRaw.length} raw deps)`, tDeps);
|
|
71
81
|
// Step 3: Get unique package names while filtering out workspace references and ignored packages
|
|
72
82
|
this.showProgress('🔍 Identifying unique packages...');
|
|
73
83
|
const uniquePackageNames = new Set();
|
|
74
84
|
const allDeps = [];
|
|
75
85
|
let ignoredCount = 0;
|
|
86
|
+
const seenWorkspaceRefs = new Set();
|
|
87
|
+
const seenIgnored = new Set();
|
|
76
88
|
for (const dep of allDepsRaw) {
|
|
77
89
|
if (this.isWorkspaceReference(dep.version)) {
|
|
90
|
+
const key = `${dep.name}@${dep.version}`;
|
|
91
|
+
if (!seenWorkspaceRefs.has(key)) {
|
|
92
|
+
seenWorkspaceRefs.add(key);
|
|
93
|
+
utils_3.debugLog.info('PackageDetector', `skipping workspace ref: ${key}`);
|
|
94
|
+
}
|
|
78
95
|
continue;
|
|
79
96
|
}
|
|
80
97
|
if (this.ignorePackages.length > 0 && (0, config_1.isPackageIgnored)(dep.name, this.ignorePackages)) {
|
|
81
98
|
ignoredCount++;
|
|
99
|
+
if (!seenIgnored.has(dep.name)) {
|
|
100
|
+
seenIgnored.add(dep.name);
|
|
101
|
+
utils_3.debugLog.info('PackageDetector', `ignoring package: ${dep.name}`);
|
|
102
|
+
}
|
|
82
103
|
continue;
|
|
83
104
|
}
|
|
84
105
|
allDeps.push(dep);
|
|
@@ -88,6 +109,7 @@ class PackageDetector {
|
|
|
88
109
|
this.showProgress(`🔍 Skipped ${ignoredCount} ignored package(s)`);
|
|
89
110
|
}
|
|
90
111
|
const packageNames = Array.from(uniquePackageNames);
|
|
112
|
+
utils_3.debugLog.info('PackageDetector', `${packageNames.length} unique packages to check, ${ignoredCount} ignored`);
|
|
91
113
|
// Step 4: Fetch all package data in one call per package
|
|
92
114
|
// Create a map of package names to their current versions for major version optimization
|
|
93
115
|
const currentVersions = new Map();
|
|
@@ -97,6 +119,8 @@ class PackageDetector {
|
|
|
97
119
|
currentVersions.set(dep.name, dep.version);
|
|
98
120
|
}
|
|
99
121
|
}
|
|
122
|
+
const tFetch = Date.now();
|
|
123
|
+
utils_3.debugLog.info('PackageDetector', `fetching version data via ${config_1.DEFAULT_REGISTRY}`);
|
|
100
124
|
const allPackageData = config_1.DEFAULT_REGISTRY === 'jsdelivr'
|
|
101
125
|
? await (0, services_1.getAllPackageDataFromJsdelivr)(packageNames, currentVersions, (_currentPackage, completed, total) => {
|
|
102
126
|
this.showProgress(`🌐 Checking versions... (${completed}/${total} packages)`);
|
|
@@ -104,12 +128,20 @@ class PackageDetector {
|
|
|
104
128
|
: await (0, services_1.getAllPackageData)(packageNames, (_currentPackage, completed, total) => {
|
|
105
129
|
this.showProgress(`🌐 Checking versions... (${completed}/${total} packages)`);
|
|
106
130
|
});
|
|
131
|
+
utils_3.debugLog.perf('PackageDetector', `registry fetch (${allPackageData.size}/${packageNames.length} resolved)`, tFetch);
|
|
132
|
+
const loggedOutdated = new Set();
|
|
133
|
+
const loggedNoData = new Set();
|
|
107
134
|
try {
|
|
108
135
|
for (const dep of allDeps) {
|
|
109
136
|
try {
|
|
110
137
|
const packageData = allPackageData.get(dep.name);
|
|
111
|
-
if (!packageData)
|
|
138
|
+
if (!packageData) {
|
|
139
|
+
if (!loggedNoData.has(dep.name)) {
|
|
140
|
+
loggedNoData.add(dep.name);
|
|
141
|
+
utils_3.debugLog.warn('PackageDetector', `no data returned for ${dep.name} — skipping`);
|
|
142
|
+
}
|
|
112
143
|
continue;
|
|
144
|
+
}
|
|
113
145
|
const { latestVersion, allVersions } = packageData;
|
|
114
146
|
// Find closest minor version (same major, higher minor) that satisfies the current range
|
|
115
147
|
// Falls back to patch updates if no minor updates are available
|
|
@@ -122,6 +154,13 @@ class PackageDetector {
|
|
|
122
154
|
const hasRangeUpdate = minorClean !== null && minorClean !== installedClean;
|
|
123
155
|
const hasMajorUpdate = semver.major(latestClean) > semver.major(installedClean);
|
|
124
156
|
const isOutdated = hasRangeUpdate || hasMajorUpdate;
|
|
157
|
+
if (isOutdated) {
|
|
158
|
+
const outdatedKey = `${dep.name}@${dep.version}`;
|
|
159
|
+
if (!loggedOutdated.has(outdatedKey)) {
|
|
160
|
+
loggedOutdated.add(outdatedKey);
|
|
161
|
+
utils_3.debugLog.info('PackageDetector', `outdated: ${dep.name} ${dep.version} → range:${closestMinorVersion ?? '-'} latest:${latestVersion}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
125
164
|
packages.push({
|
|
126
165
|
name: dep.name,
|
|
127
166
|
currentVersion: dep.version, // Keep original version specifier with prefix
|
|
@@ -135,6 +174,7 @@ class PackageDetector {
|
|
|
135
174
|
});
|
|
136
175
|
}
|
|
137
176
|
catch (error) {
|
|
177
|
+
utils_3.debugLog.error('PackageDetector', `error processing ${dep.name}`, error);
|
|
138
178
|
// Skip packages that can't be checked (private packages, etc.)
|
|
139
179
|
packages.push({
|
|
140
180
|
name: dep.name,
|
|
@@ -149,10 +189,13 @@ class PackageDetector {
|
|
|
149
189
|
});
|
|
150
190
|
}
|
|
151
191
|
}
|
|
192
|
+
const outdatedCount = packages.filter((p) => p.isOutdated).length;
|
|
193
|
+
utils_3.debugLog.perf('PackageDetector', `total scan complete (${outdatedCount} outdated of ${packages.length} deps)`, t0);
|
|
152
194
|
return packages;
|
|
153
195
|
}
|
|
154
196
|
catch (error) {
|
|
155
197
|
this.showProgress('❌ Failed to check packages\n');
|
|
198
|
+
utils_3.debugLog.error('PackageDetector', 'fatal error during package check', error);
|
|
156
199
|
throw error;
|
|
157
200
|
}
|
|
158
201
|
}
|
|
@@ -181,8 +224,7 @@ class PackageDetector {
|
|
|
181
224
|
version.startsWith('bitbucket:'));
|
|
182
225
|
}
|
|
183
226
|
showProgress(message) {
|
|
184
|
-
|
|
185
|
-
process.stdout.write(`\r${' '.repeat(80)}\r${message}`);
|
|
227
|
+
utils_2.ConsoleUtils.showProgress(message);
|
|
186
228
|
}
|
|
187
229
|
getOutdatedPackagesOnly(packages) {
|
|
188
230
|
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
|