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 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
@@ -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
- // Clear current line and show new message
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);
@@ -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
@@ -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