inup 1.4.2 → 1.4.3
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 +0 -8
- package/dist/config/constants.js +2 -24
- package/dist/core/package-detector.js +2 -5
- package/dist/core/upgrade-runner.js +2 -5
- package/dist/interactive-ui.js +17 -50
- package/dist/services/jsdelivr-registry.js +77 -88
- package/dist/ui/input-handler.js +24 -0
- package/dist/ui/renderer/index.js +2 -2
- package/dist/ui/renderer/modal.js +16 -7
- package/dist/ui/renderer/package-list.js +48 -13
- package/dist/ui/state/filter-manager.js +55 -4
- package/dist/ui/state/state-manager.js +12 -4
- package/dist/ui/state/theme-manager.js +2 -0
- package/dist/ui/themes-colors.js +12 -1
- package/dist/utils/filesystem.js +2 -16
- package/package.json +9 -4
package/dist/cli.js
CHANGED
|
@@ -18,8 +18,6 @@ program
|
|
|
18
18
|
.version(packageJson.version)
|
|
19
19
|
.option('-d, --dir <directory>', 'specify directory to run in', process.cwd())
|
|
20
20
|
.option('-e, --exclude <patterns>', 'exclude paths matching regex patterns (comma-separated)', '')
|
|
21
|
-
.option('-p, --peer', 'include peer dependencies in upgrade process')
|
|
22
|
-
.option('-o, --optional', 'include optional dependencies in upgrade process')
|
|
23
21
|
.option('--package-manager <name>', 'manually specify package manager (npm, yarn, pnpm, bun)')
|
|
24
22
|
.action(async (options) => {
|
|
25
23
|
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`);
|
|
@@ -31,10 +29,6 @@ program
|
|
|
31
29
|
.map((p) => p.trim())
|
|
32
30
|
.filter(Boolean)
|
|
33
31
|
: [];
|
|
34
|
-
// Commander.js: boolean flags are undefined if not provided, true if provided
|
|
35
|
-
// Both flags default to false (opt-in)
|
|
36
|
-
const includePeerDeps = options.peer === true;
|
|
37
|
-
const includeOptionalDeps = options.optional === true;
|
|
38
32
|
// Validate package manager if provided
|
|
39
33
|
let packageManager;
|
|
40
34
|
if (options.packageManager) {
|
|
@@ -49,8 +43,6 @@ program
|
|
|
49
43
|
const upgrader = new index_1.UpgradeRunner({
|
|
50
44
|
cwd: options.dir,
|
|
51
45
|
excludePatterns,
|
|
52
|
-
includePeerDeps,
|
|
53
|
-
includeOptionalDeps,
|
|
54
46
|
packageManager,
|
|
55
47
|
});
|
|
56
48
|
await upgrader.run();
|
package/dist/config/constants.js
CHANGED
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Constants for npm registry queries and configuration
|
|
4
|
-
*/
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
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;
|
|
4
|
+
exports.PACKAGE_NAME = 'inup';
|
|
7
5
|
exports.NPM_REGISTRY_URL = 'https://registry.npmjs.org';
|
|
8
6
|
exports.JSDELIVR_CDN_URL = 'https://cdn.jsdelivr.net/npm';
|
|
9
7
|
exports.MAX_CONCURRENT_REQUESTS = 150;
|
|
10
8
|
exports.CACHE_TTL = 5 * 60 * 1000; // 5 minutes in milliseconds
|
|
11
9
|
exports.REQUEST_TIMEOUT = 60000; // 60 seconds in milliseconds
|
|
12
|
-
/**
|
|
13
|
-
* Registry selection: 'jsdelivr' for fast CDN lookups, 'npm' for direct npm registry
|
|
14
|
-
* Set to 'npm' to use npm registry by default instead of jsdelivr
|
|
15
|
-
*/
|
|
16
10
|
exports.DEFAULT_REGISTRY = 'jsdelivr';
|
|
17
|
-
/**
|
|
18
|
-
* Package manager lock files
|
|
19
|
-
*/
|
|
20
|
-
exports.LOCK_FILES = {
|
|
21
|
-
npm: 'package-lock.json',
|
|
22
|
-
yarn: 'yarn.lock',
|
|
23
|
-
pnpm: 'pnpm-lock.yaml',
|
|
24
|
-
bun: 'bun.lockb',
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Package manager workspace files
|
|
28
|
-
*/
|
|
29
|
-
exports.WORKSPACE_FILES = {
|
|
30
|
-
pnpm: 'pnpm-workspace.yaml',
|
|
31
|
-
// npm, yarn, and bun use package.json workspaces field
|
|
32
|
-
};
|
|
33
11
|
//# sourceMappingURL=constants.js.map
|
|
@@ -44,9 +44,6 @@ class PackageDetector {
|
|
|
44
44
|
this.packageJson = null;
|
|
45
45
|
this.cwd = options?.cwd || process.cwd();
|
|
46
46
|
this.excludePatterns = options?.excludePatterns || [];
|
|
47
|
-
// Explicitly check for true to ensure false/undefined both become false (opt-in)
|
|
48
|
-
this.includePeerDeps = options?.includePeerDeps === true;
|
|
49
|
-
this.includeOptionalDeps = options?.includeOptionalDeps === true;
|
|
50
47
|
this.packageJsonPath = (0, utils_1.findPackageJson)(this.cwd);
|
|
51
48
|
if (this.packageJsonPath) {
|
|
52
49
|
this.packageJson = (0, utils_1.readPackageJson)(this.packageJsonPath);
|
|
@@ -67,8 +64,8 @@ class PackageDetector {
|
|
|
67
64
|
// Step 2: Collect all dependencies from package.json files (parallelized)
|
|
68
65
|
this.showProgress('🔍 Reading dependencies from package.json files...');
|
|
69
66
|
const allDepsRaw = await (0, utils_1.collectAllDependenciesAsync)(allPackageJsonFiles, {
|
|
70
|
-
includePeerDeps:
|
|
71
|
-
includeOptionalDeps:
|
|
67
|
+
includePeerDeps: true,
|
|
68
|
+
includeOptionalDeps: true,
|
|
72
69
|
});
|
|
73
70
|
// Step 3: Get unique package names while filtering out workspace references
|
|
74
71
|
this.showProgress('🔍 Identifying unique packages...');
|
|
@@ -44,11 +44,8 @@ class UpgradeRunner {
|
|
|
44
44
|
let shouldProceed = false;
|
|
45
45
|
let previousSelections;
|
|
46
46
|
while (true) {
|
|
47
|
-
// Interactive selection
|
|
48
|
-
selectedChoices = await this.ui.selectPackagesToUpgrade(packages, previousSelections
|
|
49
|
-
includePeerDeps: this.options?.includePeerDeps,
|
|
50
|
-
includeOptionalDeps: this.options?.includeOptionalDeps,
|
|
51
|
-
});
|
|
47
|
+
// Interactive selection
|
|
48
|
+
selectedChoices = await this.ui.selectPackagesToUpgrade(packages, previousSelections);
|
|
52
49
|
if (selectedChoices.length === 0) {
|
|
53
50
|
console.log(chalk_1.default.yellow('No packages selected. Exiting...'));
|
|
54
51
|
return;
|
package/dist/interactive-ui.js
CHANGED
|
@@ -53,51 +53,14 @@ class InteractiveUI {
|
|
|
53
53
|
async displayPackagesTable(packages) {
|
|
54
54
|
console.log(this.renderer.renderPackagesTable(packages));
|
|
55
55
|
}
|
|
56
|
-
async selectPackagesToUpgrade(packages, previousSelections
|
|
56
|
+
async selectPackagesToUpgrade(packages, previousSelections) {
|
|
57
57
|
const outdatedPackages = packages.filter((p) => p.isOutdated);
|
|
58
58
|
if (outdatedPackages.length === 0) {
|
|
59
59
|
return [];
|
|
60
60
|
}
|
|
61
|
-
// Filter packages based on CLI options.
|
|
62
|
-
// IMPORTANT: This uses an opt-in approach where:
|
|
63
|
-
// - Default (no flags): shows dependencies + devDependencies
|
|
64
|
-
// - With -p flag: shows ONLY peerDependencies (excludes dependencies)
|
|
65
|
-
// - With -o flag: shows ONLY optionalDependencies (excludes dependencies)
|
|
66
|
-
// - With -p -o flags: shows peerDependencies + optionalDependencies (excludes dependencies)
|
|
67
|
-
//
|
|
68
|
-
// This design allows users to focus on one dependency type at a time,
|
|
69
|
-
// which is useful since peer/optional deps have different upgrade semantics.
|
|
70
|
-
let filteredPackages = outdatedPackages;
|
|
71
|
-
let dependencyTypeLabel = '';
|
|
72
|
-
if (options?.includePeerDeps || options?.includeOptionalDeps) {
|
|
73
|
-
// If any special-case flag is provided, filter to show ONLY those types
|
|
74
|
-
// (excluding regular dependencies/devDependencies)
|
|
75
|
-
filteredPackages = outdatedPackages.filter((pkg) => {
|
|
76
|
-
if (options.includePeerDeps && pkg.type === 'peerDependencies')
|
|
77
|
-
return true;
|
|
78
|
-
if (options.includeOptionalDeps && pkg.type === 'optionalDependencies')
|
|
79
|
-
return true;
|
|
80
|
-
return false;
|
|
81
|
-
});
|
|
82
|
-
// Build label describing which types are shown
|
|
83
|
-
const types = [];
|
|
84
|
-
if (options.includePeerDeps)
|
|
85
|
-
types.push('Peer Deps');
|
|
86
|
-
if (options.includeOptionalDeps)
|
|
87
|
-
types.push('Optional Deps');
|
|
88
|
-
dependencyTypeLabel = types.join(' & ');
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
// Default: show only regular dependencies and devDependencies
|
|
92
|
-
filteredPackages = outdatedPackages.filter((pkg) => pkg.type === 'dependencies' || pkg.type === 'devDependencies');
|
|
93
|
-
dependencyTypeLabel = 'Deps & Dev Deps';
|
|
94
|
-
}
|
|
95
|
-
if (filteredPackages.length === 0) {
|
|
96
|
-
return [];
|
|
97
|
-
}
|
|
98
61
|
// Deduplicate packages by name and version specifier, but track all package.json paths
|
|
99
62
|
const uniquePackages = new Map();
|
|
100
|
-
for (const pkg of
|
|
63
|
+
for (const pkg of outdatedPackages) {
|
|
101
64
|
const key = `${pkg.name}@${pkg.currentVersion}`;
|
|
102
65
|
if (!uniquePackages.has(key)) {
|
|
103
66
|
uniquePackages.set(key, {
|
|
@@ -150,7 +113,7 @@ class InteractiveUI {
|
|
|
150
113
|
};
|
|
151
114
|
});
|
|
152
115
|
// Use custom interactive table selector (simplified - no grouping)
|
|
153
|
-
const selectedStates = await this.interactiveTableSelector(selectionStates
|
|
116
|
+
const selectedStates = await this.interactiveTableSelector(selectionStates);
|
|
154
117
|
// Convert to PackageUpgradeChoice[] - create one choice per package.json path
|
|
155
118
|
const choices = [];
|
|
156
119
|
selectedStates
|
|
@@ -179,7 +142,7 @@ class InteractiveUI {
|
|
|
179
142
|
}
|
|
180
143
|
return 24; // Fallback default
|
|
181
144
|
}
|
|
182
|
-
async interactiveTableSelector(selectionStates
|
|
145
|
+
async interactiveTableSelector(selectionStates) {
|
|
183
146
|
return new Promise((resolve) => {
|
|
184
147
|
const states = [...selectionStates];
|
|
185
148
|
const stateManager = new ui_1.StateManager(0, this.getTerminalHeight());
|
|
@@ -225,6 +188,11 @@ class InteractiveUI {
|
|
|
225
188
|
stateManager.bulkUnselectAll(filteredStates);
|
|
226
189
|
}
|
|
227
190
|
break;
|
|
191
|
+
case 'toggle_dep_type_filter':
|
|
192
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
193
|
+
stateManager.toggleDependencyTypeFilter(action.depType);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
228
196
|
case 'toggle_info_modal':
|
|
229
197
|
if (!uiState.showInfoModal) {
|
|
230
198
|
// Opening modal - load package info asynchronously
|
|
@@ -283,19 +251,17 @@ class InteractiveUI {
|
|
|
283
251
|
case 'theme_navigate_up': {
|
|
284
252
|
const themeManager = stateManager.getThemeManager();
|
|
285
253
|
const currentIndex = themes_1.themeNames.indexOf(themeManager.getPreviewTheme());
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
254
|
+
const themeArray = Object.keys(themes_1.themes);
|
|
255
|
+
const nextIndex = currentIndex > 0 ? currentIndex - 1 : themeArray.length - 1;
|
|
256
|
+
stateManager.previewTheme(themeArray[nextIndex]);
|
|
290
257
|
break;
|
|
291
258
|
}
|
|
292
259
|
case 'theme_navigate_down': {
|
|
293
260
|
const themeManager = stateManager.getThemeManager();
|
|
294
261
|
const currentIndex = themes_1.themeNames.indexOf(themeManager.getPreviewTheme());
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
262
|
+
const themeArray = Object.keys(themes_1.themes);
|
|
263
|
+
const nextIndex = currentIndex < themeArray.length - 1 ? currentIndex + 1 : 0;
|
|
264
|
+
stateManager.previewTheme(themeArray[nextIndex]);
|
|
299
265
|
break;
|
|
300
266
|
}
|
|
301
267
|
case 'theme_confirm':
|
|
@@ -399,8 +365,9 @@ class InteractiveUI {
|
|
|
399
365
|
else {
|
|
400
366
|
// Normal list view (flat rendering - no grouping)
|
|
401
367
|
const terminalWidth = process.stdout.columns || 80;
|
|
368
|
+
const activeFilterLabel = stateManager.getActiveFilterLabel();
|
|
402
369
|
const lines = this.renderer.renderInterface(filteredStates, uiState.currentRow, uiState.scrollOffset, uiState.maxVisibleItems, uiState.forceFullRender, [], // No renderable items - use flat rendering
|
|
403
|
-
|
|
370
|
+
activeFilterLabel, // Show current dependency type filter state
|
|
404
371
|
this.packageManager, // Pass package manager info for header
|
|
405
372
|
uiState.filterMode, uiState.filterQuery, states.length, terminalWidth);
|
|
406
373
|
// Print all lines
|
|
@@ -83,89 +83,10 @@ async function fetchPackageJsonFromJsdelivr(packageName, versionTag) {
|
|
|
83
83
|
return null;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Fetches package data from jsdelivr CDN with fallback to npm registry.
|
|
88
|
-
* Makes simultaneous requests for @latest, @major version, and current version.
|
|
89
|
-
* @param packageName - The npm package name
|
|
90
|
-
* @param currentVersion - The current version to extract major from (optional)
|
|
91
|
-
* @returns Package data with latest version and all versions
|
|
92
|
-
*/
|
|
93
|
-
async function fetchPackageFromJsdelivr(packageName, currentVersion) {
|
|
94
|
-
// Check cache first
|
|
95
|
-
const cached = packageCache.get(packageName);
|
|
96
|
-
if (cached && Date.now() - cached.timestamp < config_1.CACHE_TTL) {
|
|
97
|
-
return cached.data;
|
|
98
|
-
}
|
|
99
|
-
try {
|
|
100
|
-
// Coerce the current version in case it's a range like ^1.1.5
|
|
101
|
-
const coercedVersion = currentVersion ? semver.coerce(currentVersion)?.version : null;
|
|
102
|
-
// Determine major version from current version if provided
|
|
103
|
-
const majorVersion = currentVersion
|
|
104
|
-
? semver.major(semver.coerce(currentVersion) || '0.0.0').toString()
|
|
105
|
-
: null;
|
|
106
|
-
// Prepare requests: always fetch @latest, @major if we have a current version, and @currentVersion
|
|
107
|
-
const requests = [
|
|
108
|
-
fetchPackageJsonFromJsdelivr(packageName, 'latest'),
|
|
109
|
-
];
|
|
110
|
-
if (majorVersion) {
|
|
111
|
-
requests.push(fetchPackageJsonFromJsdelivr(packageName, majorVersion));
|
|
112
|
-
}
|
|
113
|
-
if (coercedVersion) {
|
|
114
|
-
requests.push(fetchPackageJsonFromJsdelivr(packageName, coercedVersion));
|
|
115
|
-
}
|
|
116
|
-
// Execute all requests simultaneously
|
|
117
|
-
const results = await Promise.all(requests);
|
|
118
|
-
const latestResult = results[0];
|
|
119
|
-
const majorResult = results[1];
|
|
120
|
-
const currentResult = results[2];
|
|
121
|
-
if (!latestResult) {
|
|
122
|
-
// jsdelivr doesn't have this package, fallback to npm registry
|
|
123
|
-
const npmData = await (0, npm_registry_1.getAllPackageData)([packageName]);
|
|
124
|
-
const data = npmData.get(packageName) || { latestVersion: 'unknown', allVersions: [] };
|
|
125
|
-
// Cache the result
|
|
126
|
-
packageCache.set(packageName, {
|
|
127
|
-
data,
|
|
128
|
-
timestamp: Date.now(),
|
|
129
|
-
});
|
|
130
|
-
return data;
|
|
131
|
-
}
|
|
132
|
-
const latestVersion = latestResult.version;
|
|
133
|
-
const allVersions = [latestVersion];
|
|
134
|
-
// Add the major version result if different from latest
|
|
135
|
-
if (majorResult && majorResult.version !== latestVersion) {
|
|
136
|
-
allVersions.push(majorResult.version);
|
|
137
|
-
}
|
|
138
|
-
// Add the current version result if different from latest and major
|
|
139
|
-
if (currentResult && !allVersions.includes(currentResult.version)) {
|
|
140
|
-
allVersions.push(currentResult.version);
|
|
141
|
-
}
|
|
142
|
-
const result = {
|
|
143
|
-
latestVersion,
|
|
144
|
-
allVersions: allVersions.sort(semver.rcompare),
|
|
145
|
-
};
|
|
146
|
-
// Cache the result
|
|
147
|
-
packageCache.set(packageName, {
|
|
148
|
-
data: result,
|
|
149
|
-
timestamp: Date.now(),
|
|
150
|
-
});
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
// Fallback to npm registry on any error
|
|
155
|
-
const npmData = await (0, npm_registry_1.getAllPackageData)([packageName]);
|
|
156
|
-
const data = npmData.get(packageName) || { latestVersion: 'unknown', allVersions: [] };
|
|
157
|
-
// Cache the result
|
|
158
|
-
packageCache.set(packageName, {
|
|
159
|
-
data,
|
|
160
|
-
timestamp: Date.now(),
|
|
161
|
-
});
|
|
162
|
-
return data;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
86
|
/**
|
|
166
87
|
* Fetches package version data from jsdelivr CDN for multiple packages.
|
|
167
88
|
* Uses undici connection pool for blazing fast performance with connection reuse.
|
|
168
|
-
* Falls back to npm registry if jsdelivr doesn't have
|
|
89
|
+
* Falls back to npm registry in batches if jsdelivr doesn't have packages.
|
|
169
90
|
* @param packageNames - Array of package names to fetch
|
|
170
91
|
* @param currentVersions - Optional map of package names to their current versions
|
|
171
92
|
* @param onProgress - Optional progress callback
|
|
@@ -178,19 +99,87 @@ async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onPr
|
|
|
178
99
|
}
|
|
179
100
|
const total = packageNames.length;
|
|
180
101
|
let completedCount = 0;
|
|
181
|
-
//
|
|
182
|
-
|
|
102
|
+
// Track packages that need npm fallback (not found on jsDelivr)
|
|
103
|
+
const failedPackages = [];
|
|
104
|
+
// Fire all jsDelivr requests simultaneously - undici pool handles concurrency internally
|
|
183
105
|
const allPromises = packageNames.map(async (packageName) => {
|
|
184
106
|
const currentVersion = currentVersions?.get(packageName);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
107
|
+
// Try to get from cache first
|
|
108
|
+
const cached = packageCache.get(packageName);
|
|
109
|
+
if (cached && Date.now() - cached.timestamp < config_1.CACHE_TTL) {
|
|
110
|
+
packageData.set(packageName, cached.data);
|
|
111
|
+
completedCount++;
|
|
112
|
+
if (onProgress) {
|
|
113
|
+
onProgress(packageName, completedCount, total);
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
// Determine major version from current version if provided
|
|
119
|
+
const majorVersion = currentVersion
|
|
120
|
+
? semver.major(semver.coerce(currentVersion) || '0.0.0').toString()
|
|
121
|
+
: null;
|
|
122
|
+
// Prepare requests: always fetch @latest, @major if we have a current version
|
|
123
|
+
const requests = [
|
|
124
|
+
fetchPackageJsonFromJsdelivr(packageName, 'latest'),
|
|
125
|
+
];
|
|
126
|
+
if (majorVersion) {
|
|
127
|
+
requests.push(fetchPackageJsonFromJsdelivr(packageName, majorVersion));
|
|
128
|
+
}
|
|
129
|
+
// Execute all requests simultaneously
|
|
130
|
+
const results = await Promise.all(requests);
|
|
131
|
+
const latestResult = results[0];
|
|
132
|
+
const majorResult = results[1];
|
|
133
|
+
if (!latestResult) {
|
|
134
|
+
// Package not on jsDelivr, mark for npm fallback
|
|
135
|
+
failedPackages.push(packageName);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const latestVersion = latestResult.version;
|
|
139
|
+
const allVersions = [latestVersion];
|
|
140
|
+
// Add the major version result if different from latest
|
|
141
|
+
if (majorResult && majorResult.version !== latestVersion) {
|
|
142
|
+
allVersions.push(majorResult.version);
|
|
143
|
+
}
|
|
144
|
+
const result = {
|
|
145
|
+
latestVersion,
|
|
146
|
+
allVersions: allVersions.sort(semver.rcompare),
|
|
147
|
+
};
|
|
148
|
+
// Cache the result
|
|
149
|
+
packageCache.set(packageName, {
|
|
150
|
+
data: result,
|
|
151
|
+
timestamp: Date.now(),
|
|
152
|
+
});
|
|
153
|
+
packageData.set(packageName, result);
|
|
154
|
+
completedCount++;
|
|
155
|
+
if (onProgress) {
|
|
156
|
+
onProgress(packageName, completedCount, total);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
// On error, mark for npm fallback
|
|
161
|
+
failedPackages.push(packageName);
|
|
190
162
|
}
|
|
191
163
|
});
|
|
192
|
-
// Wait for all requests to complete
|
|
164
|
+
// Wait for all jsDelivr requests to complete
|
|
193
165
|
await Promise.all(allPromises);
|
|
166
|
+
// Batch fetch all failed packages from npm registry in one call
|
|
167
|
+
if (failedPackages.length > 0) {
|
|
168
|
+
const npmData = await (0, npm_registry_1.getAllPackageData)(failedPackages, (pkg, completed, npmTotal) => {
|
|
169
|
+
completedCount++;
|
|
170
|
+
if (onProgress) {
|
|
171
|
+
onProgress(pkg, completedCount, total);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
// Merge npm data into results and cache it
|
|
175
|
+
for (const [packageName, data] of npmData.entries()) {
|
|
176
|
+
packageData.set(packageName, data);
|
|
177
|
+
packageCache.set(packageName, {
|
|
178
|
+
data,
|
|
179
|
+
timestamp: Date.now(),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
194
183
|
// Clear the progress line and show completion time if no custom progress handler
|
|
195
184
|
if (!onProgress) {
|
|
196
185
|
process.stdout.write('\r' + ' '.repeat(80) + '\r');
|
package/dist/ui/input-handler.js
CHANGED
|
@@ -24,6 +24,7 @@ class InputHandler {
|
|
|
24
24
|
if (key) {
|
|
25
25
|
switch (key.name) {
|
|
26
26
|
case 'escape':
|
|
27
|
+
// Close theme modal (which also resets theme on cancel)
|
|
27
28
|
this.onAction({ type: 'toggle_theme_modal' });
|
|
28
29
|
return;
|
|
29
30
|
case 'return':
|
|
@@ -35,6 +36,11 @@ class InputHandler {
|
|
|
35
36
|
case 'down':
|
|
36
37
|
this.onAction({ type: 'theme_navigate_down' });
|
|
37
38
|
return;
|
|
39
|
+
case 't':
|
|
40
|
+
case 'T':
|
|
41
|
+
// Allow 't' to toggle theme modal closed as well
|
|
42
|
+
this.onAction({ type: 'toggle_theme_modal' });
|
|
43
|
+
return;
|
|
38
44
|
default:
|
|
39
45
|
return;
|
|
40
46
|
}
|
|
@@ -131,6 +137,24 @@ class InputHandler {
|
|
|
131
137
|
case 'U':
|
|
132
138
|
this.onAction({ type: 'bulk_unselect_all' });
|
|
133
139
|
break;
|
|
140
|
+
case 'd':
|
|
141
|
+
case 'D':
|
|
142
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal && !uiState.filterMode) {
|
|
143
|
+
this.onAction({ type: 'toggle_dep_type_filter', depType: 'devDependencies' });
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
case 'p':
|
|
147
|
+
case 'P':
|
|
148
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal && !uiState.filterMode) {
|
|
149
|
+
this.onAction({ type: 'toggle_dep_type_filter', depType: 'peerDependencies' });
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
case 'o':
|
|
153
|
+
case 'O':
|
|
154
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal && !uiState.filterMode) {
|
|
155
|
+
this.onAction({ type: 'toggle_dep_type_filter', depType: 'optionalDependencies' });
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
134
158
|
case 'i':
|
|
135
159
|
case 'I':
|
|
136
160
|
this.onAction({ type: 'toggle_info_modal' });
|
|
@@ -54,8 +54,8 @@ class UIRenderer {
|
|
|
54
54
|
renderSpacer() {
|
|
55
55
|
return PackageList.renderSpacer();
|
|
56
56
|
}
|
|
57
|
-
renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems,
|
|
58
|
-
return PackageList.renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems,
|
|
57
|
+
renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems, activeFilterLabel, packageManager, filterMode, filterQuery, totalPackagesBeforeFilter, terminalWidth = 80) {
|
|
58
|
+
return PackageList.renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems, activeFilterLabel, packageManager, filterMode, filterQuery, totalPackagesBeforeFilter, terminalWidth);
|
|
59
59
|
}
|
|
60
60
|
renderPackagesTable(packages) {
|
|
61
61
|
return PackageList.renderPackagesTable(packages);
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.renderPackageInfoLoading = renderPackageInfoLoading;
|
|
7
7
|
exports.renderPackageInfoModal = renderPackageInfoModal;
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const themes_colors_1 = require("../themes-colors");
|
|
9
10
|
/**
|
|
10
11
|
* Remove ANSI color codes from a string for length calculation
|
|
11
12
|
*/
|
|
@@ -138,7 +139,7 @@ function renderPackageInfoModal(state, terminalWidth = 80, terminalHeight = 24)
|
|
|
138
139
|
lines.push(' '.repeat(padding) +
|
|
139
140
|
chalk_1.default.gray('│') +
|
|
140
141
|
' ' +
|
|
141
|
-
|
|
142
|
+
(0, themes_colors_1.getThemeColor)('primary')(downloadsText) +
|
|
142
143
|
' '.repeat(downloadsPadding) +
|
|
143
144
|
chalk_1.default.gray('│'));
|
|
144
145
|
}
|
|
@@ -162,20 +163,28 @@ function renderPackageInfoModal(state, terminalWidth = 80, terminalHeight = 24)
|
|
|
162
163
|
lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
|
|
163
164
|
const repoLabel = 'Changelog:';
|
|
164
165
|
const repoUrl = state.repository.substring(0, modalWidth - 20);
|
|
165
|
-
const repoText = `
|
|
166
|
+
const repoText = ` ${repoLabel} ${chalk_1.default.underline((0, themes_colors_1.getThemeColor)('primary')(repoUrl))}`;
|
|
166
167
|
const repoLength = stripAnsi(repoText).length;
|
|
167
|
-
const repoPadding = Math.max(0, modalWidth -
|
|
168
|
-
lines.push(' '.repeat(padding) +
|
|
168
|
+
const repoPadding = Math.max(0, modalWidth - 3 - repoLength);
|
|
169
|
+
lines.push(' '.repeat(padding) +
|
|
170
|
+
chalk_1.default.gray('│') +
|
|
171
|
+
repoText +
|
|
172
|
+
' '.repeat(repoPadding) +
|
|
173
|
+
chalk_1.default.gray('│'));
|
|
169
174
|
}
|
|
170
175
|
// Links section
|
|
171
176
|
if (state.homepage) {
|
|
172
177
|
lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
|
|
173
178
|
const homeLabel = 'Homepage:';
|
|
174
179
|
const homeUrl = state.homepage.substring(0, modalWidth - 20);
|
|
175
|
-
const homeText = `
|
|
180
|
+
const homeText = ` ${homeLabel} ${chalk_1.default.underline((0, themes_colors_1.getThemeColor)('primary')(homeUrl))}`;
|
|
176
181
|
const homeLength = stripAnsi(homeText).length;
|
|
177
|
-
const homePadding = Math.max(0, modalWidth -
|
|
178
|
-
lines.push(' '.repeat(padding) +
|
|
182
|
+
const homePadding = Math.max(0, modalWidth - 3 - homeLength);
|
|
183
|
+
lines.push(' '.repeat(padding) +
|
|
184
|
+
chalk_1.default.gray('│') +
|
|
185
|
+
homeText +
|
|
186
|
+
' '.repeat(homePadding) +
|
|
187
|
+
chalk_1.default.gray('│'));
|
|
179
188
|
}
|
|
180
189
|
// Footer
|
|
181
190
|
lines.push(' '.repeat(padding) + chalk_1.default.gray('╰' + '─'.repeat(modalWidth - 2) + '╯'));
|
|
@@ -11,6 +11,22 @@ exports.renderPackagesTable = renderPackagesTable;
|
|
|
11
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
12
|
const utils_1 = require("../utils");
|
|
13
13
|
const themes_colors_1 = require("../themes-colors");
|
|
14
|
+
/**
|
|
15
|
+
* Get type badge for dependency type (theme-aware)
|
|
16
|
+
*/
|
|
17
|
+
function getTypeBadge(type) {
|
|
18
|
+
switch (type) {
|
|
19
|
+
case 'devDependencies':
|
|
20
|
+
return (0, themes_colors_1.getThemeColor)('textSecondary')('[D]');
|
|
21
|
+
case 'peerDependencies':
|
|
22
|
+
return (0, themes_colors_1.getThemeColor)('textSecondary')('[P]');
|
|
23
|
+
case 'optionalDependencies':
|
|
24
|
+
return (0, themes_colors_1.getThemeColor)('textSecondary')('[O]');
|
|
25
|
+
case 'dependencies':
|
|
26
|
+
default:
|
|
27
|
+
return ''; // No badge for regular dependencies
|
|
28
|
+
}
|
|
29
|
+
}
|
|
14
30
|
/**
|
|
15
31
|
* Render a single package line
|
|
16
32
|
* @param state Package selection state
|
|
@@ -86,18 +102,23 @@ function renderPackageLine(state, index, isCurrentRow, terminalWidth = 80) {
|
|
|
86
102
|
const availableForPackageName = terminalWidth - prefixWidth - otherColumnsWidth - 1;
|
|
87
103
|
const packageNameWidth = Math.min(maxPackageNameWidth, Math.max(minPackageNameWidth, availableForPackageName));
|
|
88
104
|
// Apply ellipsis truncation if package name exceeds available width
|
|
89
|
-
const
|
|
105
|
+
const badgeWidth = state.type === 'dependencies' ? 0 : 3; // [X] without leading space
|
|
106
|
+
const truncatedName = utils_1.VersionUtils.truncateMiddle(state.name, packageNameWidth - 1 - badgeWidth); // -1 for space after name, -badgeWidth for badge
|
|
90
107
|
// Helper function to determine if dashes should be shown based on available padding
|
|
91
108
|
// Only show dashes if there's significant padding (> 2 chars) to fill
|
|
92
109
|
const shouldShowDashes = (paddingAmount) => paddingAmount > 2;
|
|
93
110
|
const dashColor = isCurrentRow ? chalk_1.default.white : chalk_1.default.gray;
|
|
94
|
-
// Package name with dashes only if needed
|
|
95
|
-
const nameLength = utils_1.VersionUtils.getVisualLength(truncatedName);
|
|
96
|
-
const namePadding = Math.max(0, packageNameWidth - nameLength - 1); // -1 for space after package name
|
|
97
|
-
const nameDashes = shouldShowDashes(namePadding) ? dashColor('-').repeat(namePadding) : ' '.repeat(namePadding);
|
|
98
111
|
// Use truncated name if it differs from original, otherwise use colored packageName
|
|
99
112
|
const displayName = truncatedName !== state.name ? truncatedName : packageName;
|
|
100
|
-
|
|
113
|
+
// Package name with dashes and badge at the end
|
|
114
|
+
const typeBadge = getTypeBadge(state.type);
|
|
115
|
+
const nameLength = utils_1.VersionUtils.getVisualLength(truncatedName);
|
|
116
|
+
const namePadding = Math.max(0, packageNameWidth - nameLength - 1 - badgeWidth); // -1 for space after package name, -badgeWidth for badge at end
|
|
117
|
+
const nameDashes = shouldShowDashes(namePadding) ? dashColor('-').repeat(namePadding) : ' '.repeat(namePadding);
|
|
118
|
+
// Place badge at the end of dashes: name ------[D]
|
|
119
|
+
const packageNameSection = typeBadge
|
|
120
|
+
? `${displayName} ${nameDashes}${typeBadge}`
|
|
121
|
+
: `${displayName} ${nameDashes}`;
|
|
101
122
|
// Current version section with dashes only if needed
|
|
102
123
|
const currentSection = `${currentDot} ${currentVersion}`;
|
|
103
124
|
const currentSectionLength = utils_1.VersionUtils.getVisualLength(currentSection) + 1; // +1 for space before padding
|
|
@@ -150,7 +171,7 @@ function renderSpacer() {
|
|
|
150
171
|
/**
|
|
151
172
|
* Render the main interface
|
|
152
173
|
*/
|
|
153
|
-
function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems,
|
|
174
|
+
function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forceFullRender, renderableItems, activeFilterLabel, packageManager, filterMode, filterQuery, totalPackagesBeforeFilter, terminalWidth = 80) {
|
|
154
175
|
const output = [];
|
|
155
176
|
// Header section (same for initial and incremental render)
|
|
156
177
|
if (packageManager) {
|
|
@@ -166,17 +187,31 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
166
187
|
const inupColors = [chalk_1.default.red, chalk_1.default.yellow, chalk_1.default.blue, chalk_1.default.magenta];
|
|
167
188
|
const coloredInup = inupColors.map((color, i) => color.bold('inup'[i])).join('');
|
|
168
189
|
const headerLine = ' ' + chalk_1.default.bold(pmColor('🚀')) + ' ' + coloredInup + (0, themes_colors_1.getThemeColor)('textSecondary')(` (${packageManager.displayName})`);
|
|
169
|
-
|
|
190
|
+
// Show filter state (always show, including "All")
|
|
191
|
+
const fullHeaderLine = activeFilterLabel
|
|
192
|
+
? headerLine + (0, themes_colors_1.getThemeColor)('textSecondary')(' - ') + (0, themes_colors_1.getThemeColor)('primary')(activeFilterLabel)
|
|
193
|
+
: headerLine;
|
|
194
|
+
// Pad to terminal width to clear any leftover characters
|
|
195
|
+
const headerPadding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(fullHeaderLine));
|
|
196
|
+
output.push(fullHeaderLine + ' '.repeat(headerPadding));
|
|
170
197
|
}
|
|
171
198
|
else {
|
|
172
199
|
const headerLine = ' ' + 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');
|
|
173
|
-
|
|
200
|
+
// Show filter state (always show, including "All")
|
|
201
|
+
const fullHeaderLine = activeFilterLabel
|
|
202
|
+
? headerLine + (0, themes_colors_1.getThemeColor)('textSecondary')(' - ') + (0, themes_colors_1.getThemeColor)('primary')(activeFilterLabel)
|
|
203
|
+
: headerLine;
|
|
204
|
+
// Pad to terminal width to clear any leftover characters
|
|
205
|
+
const headerPadding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(fullHeaderLine));
|
|
206
|
+
output.push(fullHeaderLine + ' '.repeat(headerPadding));
|
|
174
207
|
}
|
|
175
208
|
output.push('');
|
|
176
209
|
if (filterMode) {
|
|
177
210
|
// Show filter input with cursor when actively filtering
|
|
178
211
|
const filterDisplay = ' ' + chalk_1.default.bold.white('Search: ') + (0, themes_colors_1.getThemeColor)('primary')(filterQuery || '') + (0, themes_colors_1.getThemeColor)('border')('█');
|
|
179
|
-
|
|
212
|
+
// Pad to terminal width to clear any leftover characters from backspace
|
|
213
|
+
const padding = Math.max(0, terminalWidth - utils_1.VersionUtils.getVisualLength(filterDisplay));
|
|
214
|
+
output.push(filterDisplay + ' '.repeat(padding));
|
|
180
215
|
}
|
|
181
216
|
else {
|
|
182
217
|
// Show instructions when not filtering
|
|
@@ -190,12 +225,12 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
190
225
|
chalk_1.default.bold.white('←/→ ') +
|
|
191
226
|
(0, themes_colors_1.getThemeColor)('textSecondary')('Select') +
|
|
192
227
|
' ' +
|
|
228
|
+
chalk_1.default.bold.white('D/P/O ') +
|
|
229
|
+
(0, themes_colors_1.getThemeColor)('textSecondary')('Filter') +
|
|
230
|
+
' ' +
|
|
193
231
|
chalk_1.default.bold.white('I ') +
|
|
194
232
|
(0, themes_colors_1.getThemeColor)('textSecondary')('Info') +
|
|
195
233
|
' ' +
|
|
196
|
-
chalk_1.default.bold.white('T ') +
|
|
197
|
-
(0, themes_colors_1.getThemeColor)('textSecondary')('Theme') +
|
|
198
|
-
' ' +
|
|
199
234
|
chalk_1.default.bold.white('M ') +
|
|
200
235
|
(0, themes_colors_1.getThemeColor)('textSecondary')('Minor') +
|
|
201
236
|
' ' +
|
|
@@ -6,6 +6,10 @@ class FilterManager {
|
|
|
6
6
|
this.state = {
|
|
7
7
|
filterMode: false,
|
|
8
8
|
filterQuery: '',
|
|
9
|
+
showDependencies: true,
|
|
10
|
+
showDevDependencies: true,
|
|
11
|
+
showPeerDependencies: true,
|
|
12
|
+
showOptionalDependencies: true,
|
|
9
13
|
};
|
|
10
14
|
}
|
|
11
15
|
getState() {
|
|
@@ -36,12 +40,59 @@ class FilterManager {
|
|
|
36
40
|
this.state.filterQuery = this.state.filterQuery.slice(0, -1);
|
|
37
41
|
}
|
|
38
42
|
}
|
|
43
|
+
toggleDependencyType(type) {
|
|
44
|
+
switch (type) {
|
|
45
|
+
case 'dependencies':
|
|
46
|
+
this.state.showDependencies = !this.state.showDependencies;
|
|
47
|
+
break;
|
|
48
|
+
case 'devDependencies':
|
|
49
|
+
this.state.showDevDependencies = !this.state.showDevDependencies;
|
|
50
|
+
break;
|
|
51
|
+
case 'peerDependencies':
|
|
52
|
+
this.state.showPeerDependencies = !this.state.showPeerDependencies;
|
|
53
|
+
break;
|
|
54
|
+
case 'optionalDependencies':
|
|
55
|
+
this.state.showOptionalDependencies = !this.state.showOptionalDependencies;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
getActiveFilterLabel() {
|
|
60
|
+
const activeTypes = [];
|
|
61
|
+
if (this.state.showDependencies)
|
|
62
|
+
activeTypes.push('Deps');
|
|
63
|
+
if (this.state.showDevDependencies)
|
|
64
|
+
activeTypes.push('Dev');
|
|
65
|
+
if (this.state.showPeerDependencies)
|
|
66
|
+
activeTypes.push('Peer');
|
|
67
|
+
if (this.state.showOptionalDependencies)
|
|
68
|
+
activeTypes.push('Optional');
|
|
69
|
+
if (activeTypes.length === 0)
|
|
70
|
+
return 'None';
|
|
71
|
+
return activeTypes.join(', ');
|
|
72
|
+
}
|
|
39
73
|
getFilteredStates(allStates) {
|
|
40
|
-
|
|
41
|
-
|
|
74
|
+
let filtered = allStates;
|
|
75
|
+
// Apply text filter
|
|
76
|
+
if (this.state.filterQuery) {
|
|
77
|
+
const query = this.state.filterQuery.toLowerCase();
|
|
78
|
+
filtered = filtered.filter((state) => state.name.toLowerCase().includes(query));
|
|
42
79
|
}
|
|
43
|
-
|
|
44
|
-
|
|
80
|
+
// Apply dependency type filter
|
|
81
|
+
filtered = filtered.filter((state) => {
|
|
82
|
+
switch (state.type) {
|
|
83
|
+
case 'dependencies':
|
|
84
|
+
return this.state.showDependencies;
|
|
85
|
+
case 'devDependencies':
|
|
86
|
+
return this.state.showDevDependencies;
|
|
87
|
+
case 'peerDependencies':
|
|
88
|
+
return this.state.showPeerDependencies;
|
|
89
|
+
case 'optionalDependencies':
|
|
90
|
+
return this.state.showOptionalDependencies;
|
|
91
|
+
default:
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return filtered;
|
|
45
96
|
}
|
|
46
97
|
}
|
|
47
98
|
exports.FilterManager = FilterManager;
|
|
@@ -163,13 +163,13 @@ class StateManager {
|
|
|
163
163
|
// Filter delegation
|
|
164
164
|
enterFilterMode() {
|
|
165
165
|
this.filterManager.enterFilterMode();
|
|
166
|
-
|
|
166
|
+
// Use incremental render for search mode toggle (no blink)
|
|
167
167
|
}
|
|
168
168
|
exitFilterMode() {
|
|
169
169
|
this.filterManager.exitFilterMode();
|
|
170
170
|
this.navigationManager.setCurrentRow(0);
|
|
171
171
|
this.navigationManager.setScrollOffset(0);
|
|
172
|
-
|
|
172
|
+
// Use incremental render for search mode toggle (no blink)
|
|
173
173
|
}
|
|
174
174
|
updateFilterQuery(query) {
|
|
175
175
|
this.filterManager.updateFilterQuery(query);
|
|
@@ -180,17 +180,25 @@ class StateManager {
|
|
|
180
180
|
this.filterManager.appendToFilterQuery(char);
|
|
181
181
|
this.navigationManager.setCurrentRow(0);
|
|
182
182
|
this.navigationManager.setScrollOffset(0);
|
|
183
|
-
this.renderState.forceFullRender = true;
|
|
184
183
|
}
|
|
185
184
|
deleteFromFilterQuery() {
|
|
186
185
|
this.filterManager.deleteFromFilterQuery();
|
|
187
186
|
this.navigationManager.setCurrentRow(0);
|
|
188
187
|
this.navigationManager.setScrollOffset(0);
|
|
189
|
-
this.renderState.forceFullRender = true;
|
|
190
188
|
}
|
|
191
189
|
getFilteredStates(allStates) {
|
|
192
190
|
return this.filterManager.getFilteredStates(allStates);
|
|
193
191
|
}
|
|
192
|
+
toggleDependencyTypeFilter(type) {
|
|
193
|
+
this.filterManager.toggleDependencyType(type);
|
|
194
|
+
// Reset navigation when filter changes
|
|
195
|
+
this.navigationManager.setCurrentRow(0);
|
|
196
|
+
this.navigationManager.setScrollOffset(0);
|
|
197
|
+
// Use incremental render (no blink)
|
|
198
|
+
}
|
|
199
|
+
getActiveFilterLabel() {
|
|
200
|
+
return this.filterManager.getActiveFilterLabel();
|
|
201
|
+
}
|
|
194
202
|
// Display and render state management
|
|
195
203
|
updateTerminalHeight(newHeight) {
|
|
196
204
|
const newMaxVisibleItems = Math.max(5, newHeight - this.headerLines - 2);
|
|
@@ -40,6 +40,8 @@ class ThemeManager {
|
|
|
40
40
|
this.state.showThemeModal = false;
|
|
41
41
|
// Reset preview to current theme when closing without confirmation
|
|
42
42
|
this.state.previewTheme = this.state.currentTheme;
|
|
43
|
+
// Restore global theme to confirmed theme when canceling
|
|
44
|
+
globalCurrentTheme = this.state.currentTheme;
|
|
43
45
|
}
|
|
44
46
|
previewTheme(themeName) {
|
|
45
47
|
if (themes_1.themeNames.includes(themeName)) {
|
package/dist/ui/themes-colors.js
CHANGED
|
@@ -24,7 +24,7 @@ const themeColorDefinitions = {
|
|
|
24
24
|
textSecondary: 'gray',
|
|
25
25
|
},
|
|
26
26
|
dracula: {
|
|
27
|
-
bg: '#
|
|
27
|
+
bg: '#1e1f26',
|
|
28
28
|
primary: '#8BE9FD',
|
|
29
29
|
secondary: '#FF79C6',
|
|
30
30
|
success: '#50FA7B',
|
|
@@ -78,6 +78,17 @@ const themeColorDefinitions = {
|
|
|
78
78
|
text: '#C0CAF5',
|
|
79
79
|
textSecondary: '#A9B1D6',
|
|
80
80
|
},
|
|
81
|
+
onedark: {
|
|
82
|
+
bg: '#282c34',
|
|
83
|
+
primary: '#61AFEF',
|
|
84
|
+
secondary: '#C678DD',
|
|
85
|
+
success: '#98C379',
|
|
86
|
+
warning: '#E5C07B',
|
|
87
|
+
error: '#E06C75',
|
|
88
|
+
border: '#3E4452',
|
|
89
|
+
text: '#ABB2BF',
|
|
90
|
+
textSecondary: '#5C6370',
|
|
91
|
+
},
|
|
81
92
|
};
|
|
82
93
|
// Helper to apply color - handles both hex and named colors
|
|
83
94
|
function applyColor(color, text) {
|
package/dist/utils/filesystem.js
CHANGED
|
@@ -61,18 +61,11 @@ async function readPackageJsonAsync(path) {
|
|
|
61
61
|
* Optionally includes peer and optional dependencies based on flags.
|
|
62
62
|
*/
|
|
63
63
|
function collectAllDependencies(packageJsonFiles, options = {}) {
|
|
64
|
-
const { includePeerDeps = false, includeOptionalDeps = false } = options;
|
|
65
64
|
const allDeps = [];
|
|
66
65
|
for (const packageJsonPath of packageJsonFiles) {
|
|
67
66
|
try {
|
|
68
67
|
const packageJson = readPackageJson(packageJsonPath);
|
|
69
|
-
const depTypes = ['dependencies', 'devDependencies'];
|
|
70
|
-
if (includeOptionalDeps) {
|
|
71
|
-
depTypes.push('optionalDependencies');
|
|
72
|
-
}
|
|
73
|
-
if (includePeerDeps) {
|
|
74
|
-
depTypes.push('peerDependencies');
|
|
75
|
-
}
|
|
68
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
76
69
|
for (const depType of depTypes) {
|
|
77
70
|
const deps = packageJson[depType];
|
|
78
71
|
if (deps && typeof deps === 'object') {
|
|
@@ -100,7 +93,6 @@ function collectAllDependencies(packageJsonFiles, options = {}) {
|
|
|
100
93
|
* Optionally includes peer and optional dependencies based on flags.
|
|
101
94
|
*/
|
|
102
95
|
async function collectAllDependenciesAsync(packageJsonFiles, options = {}) {
|
|
103
|
-
const { includePeerDeps = false, includeOptionalDeps = false } = options;
|
|
104
96
|
// Read all package.json files in parallel
|
|
105
97
|
const packageJsonPromises = packageJsonFiles.map(async (packageJsonPath) => {
|
|
106
98
|
try {
|
|
@@ -119,13 +111,7 @@ async function collectAllDependenciesAsync(packageJsonFiles, options = {}) {
|
|
|
119
111
|
if (!result)
|
|
120
112
|
continue;
|
|
121
113
|
const { packageJson, packageJsonPath } = result;
|
|
122
|
-
const depTypes = ['dependencies', 'devDependencies'];
|
|
123
|
-
if (includeOptionalDeps) {
|
|
124
|
-
depTypes.push('optionalDependencies');
|
|
125
|
-
}
|
|
126
|
-
if (includePeerDeps) {
|
|
127
|
-
depTypes.push('peerDependencies');
|
|
128
|
-
}
|
|
114
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
129
115
|
for (const depType of depTypes) {
|
|
130
116
|
const deps = packageJson[depType];
|
|
131
117
|
if (deps && typeof deps === 'object') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inup",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.3",
|
|
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": {
|
|
@@ -37,11 +37,13 @@
|
|
|
37
37
|
],
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/inquirer": "^9.0.9",
|
|
40
|
-
"@types/keypress": "^2.
|
|
40
|
+
"@types/keypress.js": "^2.1.3",
|
|
41
41
|
"@types/node": "^24.10.1",
|
|
42
42
|
"@types/semver": "^7.7.1",
|
|
43
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
43
44
|
"prettier": "^3.8.0",
|
|
44
|
-
"typescript": "^5.9.3"
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"vitest": "^3.0.0"
|
|
45
47
|
},
|
|
46
48
|
"dependencies": {
|
|
47
49
|
"chalk": "^5.6.2",
|
|
@@ -67,6 +69,9 @@
|
|
|
67
69
|
"format": "prettier --write src/**/*.ts",
|
|
68
70
|
"format:check": "prettier --check src/**/*.ts",
|
|
69
71
|
"demo:record": "bash docs/demo/record-demo.sh",
|
|
70
|
-
"demo:setup": "cd docs/demo-project && pnpm install"
|
|
72
|
+
"demo:setup": "cd docs/demo-project && pnpm install",
|
|
73
|
+
"test": "vitest run",
|
|
74
|
+
"test:watch": "vitest",
|
|
75
|
+
"test:coverage": "vitest run --coverage"
|
|
71
76
|
}
|
|
72
77
|
}
|