inup 1.4.1 → 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/README.md +30 -114
- 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 +74 -52
- package/dist/services/jsdelivr-registry.js +77 -88
- package/dist/ui/index.js +18 -14
- package/dist/ui/input-handler.js +50 -0
- package/dist/ui/renderer/index.js +7 -2
- package/dist/ui/renderer/modal.js +16 -7
- package/dist/ui/renderer/package-list.js +125 -70
- package/dist/ui/renderer/theme-selector.js +83 -0
- package/dist/ui/state/filter-manager.js +55 -4
- package/dist/ui/state/state-manager.js +37 -4
- package/dist/ui/state/theme-manager.js +87 -0
- package/dist/ui/themes-colors.js +179 -0
- package/dist/ui/themes.js +27 -0
- package/dist/ui/utils/version.js +23 -0
- package/dist/utils/config.js +57 -0
- package/dist/utils/filesystem.js +2 -16
- package/package.json +23 -19
package/README.md
CHANGED
|
@@ -4,46 +4,17 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/inup)
|
|
5
5
|
[](https://www.npmjs.com/package/inup)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Interactive upgrade for your dependencies. Works with npm, yarn, pnpm, and bun.
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
Ever found yourself staring at a wall of outdated packages, wondering which ones to upgrade? This tool helps you:
|
|
14
|
-
|
|
15
|
-
- **Scans your entire project** - finds all package.json files in your workspace
|
|
16
|
-
- **Auto-detects your package manager** - works seamlessly with npm, yarn, pnpm, or bun
|
|
17
|
-
- **Checks for updates** - compares your current versions against the latest available
|
|
18
|
-
- **Lets you pick what to upgrade** - interactive interface to select exactly what you want
|
|
19
|
-
- **Does the heavy lifting** - updates your package.json files and runs the appropriate install command
|
|
20
|
-
|
|
21
|
-
## Why choose inup?
|
|
22
|
-
|
|
23
|
-
If you miss the convenience of `yarn upgrade-interactive` but want it to work with **any package manager**, this tool is perfect for you!
|
|
24
|
-
|
|
25
|
-
- **🚀 Fast & Efficient** - Batch upgrade multiple packages at once
|
|
26
|
-
- **🔒 Safe Updates** - Choose between minor updates or major version jumps
|
|
27
|
-
- **🏢 Monorepo Friendly** - Works seamlessly with workspaces
|
|
28
|
-
- **📦 Registry Aware** - Checks npm registry for latest versions
|
|
29
|
-
- **🎯 Selective Upgrades** - Pick exactly which packages to upgrade
|
|
30
|
-
- **⚡ Zero Config** - Works out of the box with sensible defaults
|
|
31
|
-
|
|
32
|
-
## Installation
|
|
33
|
-
|
|
34
|
-
### With npx (no installation needed)
|
|
11
|
+
## Install
|
|
35
12
|
|
|
36
13
|
```bash
|
|
37
14
|
npx inup
|
|
38
15
|
```
|
|
39
16
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
pnpm add -g inup
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Alternative: npm
|
|
17
|
+
Or install globally:
|
|
47
18
|
|
|
48
19
|
```bash
|
|
49
20
|
npm install -g inup
|
|
@@ -51,101 +22,46 @@ npm install -g inup
|
|
|
51
22
|
|
|
52
23
|
## Usage
|
|
53
24
|
|
|
54
|
-
Just run it in your project directory:
|
|
55
|
-
|
|
56
25
|
```bash
|
|
57
|
-
inup
|
|
26
|
+
npx inup
|
|
58
27
|
```
|
|
59
28
|
|
|
60
|
-
The tool
|
|
61
|
-
|
|
62
|
-
### Interactive Features
|
|
29
|
+
That's it. The tool scans your project, finds outdated packages, and lets you pick what to upgrade.
|
|
63
30
|
|
|
64
|
-
|
|
65
|
-
- **Navigate**: Use arrow keys to move between packages
|
|
66
|
-
- **Select Version**: Use `Left` and `Right` arrow keys to cycle through available versions (default, minor, patch, major)
|
|
67
|
-
- **Select All Minor**: Press `m` to select all minor updates
|
|
68
|
-
- **Package Info**: Press `i` to view detailed information about the selected package
|
|
69
|
-
- **Exit Search**: Press `Esc` to exit search mode
|
|
31
|
+
## Features
|
|
70
32
|
|
|
71
|
-
|
|
33
|
+
- Auto-detects package manager (npm, yarn, pnpm, bun)
|
|
34
|
+
- Works with monorepos and workspaces
|
|
35
|
+
- Batch upgrades with keyboard shortcuts
|
|
36
|
+
- Search packages with `/`
|
|
37
|
+
- Multiple themes (press `t`)
|
|
38
|
+
- Package info modal (press `i`)
|
|
72
39
|
|
|
73
|
-
|
|
74
|
-
- `-e, --exclude <patterns>`: Skip directories matching these regex patterns (comma-separated)
|
|
75
|
-
- `-p, --peer`: Include peer dependencies in upgrade process (default: false)
|
|
76
|
-
- `-o, --optional`: Include optional dependencies in upgrade process (default: false)
|
|
77
|
-
- `--package-manager <name>`: Manually specify package manager (npm, yarn, pnpm, bun) - overrides auto-detection
|
|
40
|
+
## Keyboard Shortcuts
|
|
78
41
|
|
|
79
|
-
|
|
42
|
+
- `↑/↓` - Navigate packages
|
|
43
|
+
- `←/→` - Select version (current, patch, minor, major)
|
|
44
|
+
- `Space` - Toggle selection
|
|
45
|
+
- `m` - Select all minor updates
|
|
46
|
+
- `l` - Select all latest updates
|
|
47
|
+
- `u` - Unselect all
|
|
48
|
+
- `/` - Search packages
|
|
49
|
+
- `t` - Change theme
|
|
50
|
+
- `i` - View package info
|
|
51
|
+
- `Enter` - Confirm and upgrade
|
|
80
52
|
|
|
81
|
-
|
|
53
|
+
## Options
|
|
82
54
|
|
|
83
55
|
```bash
|
|
84
|
-
|
|
85
|
-
inup
|
|
86
|
-
|
|
87
|
-
# Include peer dependencies in the upgrade process
|
|
88
|
-
inup --peer
|
|
89
|
-
|
|
90
|
-
# Include optional dependencies
|
|
91
|
-
inup --optional
|
|
56
|
+
inup [options]
|
|
92
57
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# Skip specific paths with regex
|
|
100
|
-
inup -e "example/.*,.*\.test\..*"
|
|
101
|
-
|
|
102
|
-
# Run in a different directory
|
|
103
|
-
inup --dir ../my-other-project
|
|
104
|
-
|
|
105
|
-
# Combine multiple options
|
|
106
|
-
inup --dir ./packages --peer --exclude "test,dist"
|
|
107
|
-
|
|
108
|
-
# Force a specific package manager
|
|
109
|
-
inup --package-manager npm
|
|
58
|
+
-d, --dir <path> Run in specific directory
|
|
59
|
+
-e, --exclude <patterns> Skip directories (comma-separated regex)
|
|
60
|
+
-p, --peer Include peer dependencies
|
|
61
|
+
-o, --optional Include optional dependencies
|
|
62
|
+
--package-manager <name> Force package manager (npm, yarn, pnpm, bun)
|
|
110
63
|
```
|
|
111
64
|
|
|
112
|
-
### How it works
|
|
113
|
-
|
|
114
|
-
1. **Detects your package manager** - Auto-detects from lock files (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) or package.json
|
|
115
|
-
2. **Scans your project** - Finds all package.json files recursively (respects exclude patterns)
|
|
116
|
-
3. **Collects dependencies** - Gathers dependencies based on your options (dependencies, devDependencies, and optionally peerDependencies/optionalDependencies)
|
|
117
|
-
4. **Checks for updates** - Queries npm registry for latest versions
|
|
118
|
-
5. **Shows you options** - Interactive UI lets you pick what to upgrade (minor updates or latest versions)
|
|
119
|
-
6. **Updates safely** - Modifies package.json files and runs the appropriate install command (`npm install`, `yarn install`, `pnpm install`, or `bun install`)
|
|
120
|
-
|
|
121
|
-
### Package Manager Detection
|
|
122
|
-
|
|
123
|
-
inup automatically detects which package manager you're using by:
|
|
124
|
-
|
|
125
|
-
1. **Checking package.json** - Looks for the `packageManager` field
|
|
126
|
-
2. **Checking lock files** - Scans for:
|
|
127
|
-
- `pnpm-lock.yaml` → pnpm
|
|
128
|
-
- `bun.lockb` → bun
|
|
129
|
-
- `yarn.lock` → yarn
|
|
130
|
-
- `package-lock.json` → npm
|
|
131
|
-
3. **Fallback to npm** - If nothing is detected, defaults to npm with a warning
|
|
132
|
-
|
|
133
|
-
You can override auto-detection using the `--package-manager` flag.
|
|
134
|
-
|
|
135
|
-
### FAQ
|
|
136
|
-
|
|
137
|
-
**Q: How does inup detect my package manager?**
|
|
138
|
-
A: It checks your `package.json` `packageManager` field first, then looks for lock files. You can manually override with `--package-manager`.
|
|
139
|
-
|
|
140
|
-
**Q: What if I have multiple lock files?**
|
|
141
|
-
A: inup will use the most recently modified lock file and show a warning. Consider cleaning up unused lock files.
|
|
142
|
-
|
|
143
|
-
**Q: Can I force a specific package manager?**
|
|
144
|
-
A: Yes! Use `--package-manager npm` (or yarn, pnpm, bun) to override auto-detection.
|
|
145
|
-
|
|
146
|
-
**Q: What if the detected package manager isn't installed?**
|
|
147
|
-
A: inup will still update your package.json files but skip the install step. It will show you the manual install command to run.
|
|
148
|
-
|
|
149
65
|
## License
|
|
150
66
|
|
|
151
67
|
MIT
|
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
|
@@ -43,6 +43,8 @@ const semver = __importStar(require("semver"));
|
|
|
43
43
|
const keypress = require('keypress');
|
|
44
44
|
const ui_1 = require("./ui");
|
|
45
45
|
const services_1 = require("./services");
|
|
46
|
+
const themes_1 = require("./ui/themes");
|
|
47
|
+
const themes_colors_1 = require("./ui/themes-colors");
|
|
46
48
|
class InteractiveUI {
|
|
47
49
|
constructor(packageManager) {
|
|
48
50
|
this.renderer = new ui_1.UIRenderer();
|
|
@@ -51,51 +53,14 @@ class InteractiveUI {
|
|
|
51
53
|
async displayPackagesTable(packages) {
|
|
52
54
|
console.log(this.renderer.renderPackagesTable(packages));
|
|
53
55
|
}
|
|
54
|
-
async selectPackagesToUpgrade(packages, previousSelections
|
|
56
|
+
async selectPackagesToUpgrade(packages, previousSelections) {
|
|
55
57
|
const outdatedPackages = packages.filter((p) => p.isOutdated);
|
|
56
58
|
if (outdatedPackages.length === 0) {
|
|
57
59
|
return [];
|
|
58
60
|
}
|
|
59
|
-
// Filter packages based on CLI options.
|
|
60
|
-
// IMPORTANT: This uses an opt-in approach where:
|
|
61
|
-
// - Default (no flags): shows dependencies + devDependencies
|
|
62
|
-
// - With -p flag: shows ONLY peerDependencies (excludes dependencies)
|
|
63
|
-
// - With -o flag: shows ONLY optionalDependencies (excludes dependencies)
|
|
64
|
-
// - With -p -o flags: shows peerDependencies + optionalDependencies (excludes dependencies)
|
|
65
|
-
//
|
|
66
|
-
// This design allows users to focus on one dependency type at a time,
|
|
67
|
-
// which is useful since peer/optional deps have different upgrade semantics.
|
|
68
|
-
let filteredPackages = outdatedPackages;
|
|
69
|
-
let dependencyTypeLabel = '';
|
|
70
|
-
if (options?.includePeerDeps || options?.includeOptionalDeps) {
|
|
71
|
-
// If any special-case flag is provided, filter to show ONLY those types
|
|
72
|
-
// (excluding regular dependencies/devDependencies)
|
|
73
|
-
filteredPackages = outdatedPackages.filter((pkg) => {
|
|
74
|
-
if (options.includePeerDeps && pkg.type === 'peerDependencies')
|
|
75
|
-
return true;
|
|
76
|
-
if (options.includeOptionalDeps && pkg.type === 'optionalDependencies')
|
|
77
|
-
return true;
|
|
78
|
-
return false;
|
|
79
|
-
});
|
|
80
|
-
// Build label describing which types are shown
|
|
81
|
-
const types = [];
|
|
82
|
-
if (options.includePeerDeps)
|
|
83
|
-
types.push('Peer Deps');
|
|
84
|
-
if (options.includeOptionalDeps)
|
|
85
|
-
types.push('Optional Deps');
|
|
86
|
-
dependencyTypeLabel = types.join(' & ');
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
// Default: show only regular dependencies and devDependencies
|
|
90
|
-
filteredPackages = outdatedPackages.filter((pkg) => pkg.type === 'dependencies' || pkg.type === 'devDependencies');
|
|
91
|
-
dependencyTypeLabel = 'Deps & Dev Deps';
|
|
92
|
-
}
|
|
93
|
-
if (filteredPackages.length === 0) {
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
61
|
// Deduplicate packages by name and version specifier, but track all package.json paths
|
|
97
62
|
const uniquePackages = new Map();
|
|
98
|
-
for (const pkg of
|
|
63
|
+
for (const pkg of outdatedPackages) {
|
|
99
64
|
const key = `${pkg.name}@${pkg.currentVersion}`;
|
|
100
65
|
if (!uniquePackages.has(key)) {
|
|
101
66
|
uniquePackages.set(key, {
|
|
@@ -148,7 +113,7 @@ class InteractiveUI {
|
|
|
148
113
|
};
|
|
149
114
|
});
|
|
150
115
|
// Use custom interactive table selector (simplified - no grouping)
|
|
151
|
-
const selectedStates = await this.interactiveTableSelector(selectionStates
|
|
116
|
+
const selectedStates = await this.interactiveTableSelector(selectionStates);
|
|
152
117
|
// Convert to PackageUpgradeChoice[] - create one choice per package.json path
|
|
153
118
|
const choices = [];
|
|
154
119
|
selectedStates
|
|
@@ -177,7 +142,7 @@ class InteractiveUI {
|
|
|
177
142
|
}
|
|
178
143
|
return 24; // Fallback default
|
|
179
144
|
}
|
|
180
|
-
async interactiveTableSelector(selectionStates
|
|
145
|
+
async interactiveTableSelector(selectionStates) {
|
|
181
146
|
return new Promise((resolve) => {
|
|
182
147
|
const states = [...selectionStates];
|
|
183
148
|
const stateManager = new ui_1.StateManager(0, this.getTerminalHeight());
|
|
@@ -189,40 +154,45 @@ class InteractiveUI {
|
|
|
189
154
|
const filteredStates = stateManager.getFilteredStates(states);
|
|
190
155
|
switch (action.type) {
|
|
191
156
|
case 'navigate_up':
|
|
192
|
-
if (!uiState.showInfoModal) {
|
|
157
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
193
158
|
stateManager.navigateUp(filteredStates.length);
|
|
194
159
|
}
|
|
195
160
|
break;
|
|
196
161
|
case 'navigate_down':
|
|
197
|
-
if (!uiState.showInfoModal) {
|
|
162
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
198
163
|
stateManager.navigateDown(filteredStates.length);
|
|
199
164
|
}
|
|
200
165
|
break;
|
|
201
166
|
case 'select_left':
|
|
202
|
-
if (!uiState.showInfoModal) {
|
|
167
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
203
168
|
stateManager.updateSelection(filteredStates, 'left');
|
|
204
169
|
}
|
|
205
170
|
break;
|
|
206
171
|
case 'select_right':
|
|
207
|
-
if (!uiState.showInfoModal) {
|
|
172
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
208
173
|
stateManager.updateSelection(filteredStates, 'right');
|
|
209
174
|
}
|
|
210
175
|
break;
|
|
211
176
|
case 'bulk_select_minor':
|
|
212
|
-
if (!uiState.showInfoModal) {
|
|
177
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
213
178
|
stateManager.bulkSelectMinor(filteredStates);
|
|
214
179
|
}
|
|
215
180
|
break;
|
|
216
181
|
case 'bulk_select_latest':
|
|
217
|
-
if (!uiState.showInfoModal) {
|
|
182
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
218
183
|
stateManager.bulkSelectLatest(filteredStates);
|
|
219
184
|
}
|
|
220
185
|
break;
|
|
221
186
|
case 'bulk_unselect_all':
|
|
222
|
-
if (!uiState.showInfoModal) {
|
|
187
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
223
188
|
stateManager.bulkUnselectAll(filteredStates);
|
|
224
189
|
}
|
|
225
190
|
break;
|
|
191
|
+
case 'toggle_dep_type_filter':
|
|
192
|
+
if (!uiState.showInfoModal && !uiState.showThemeModal) {
|
|
193
|
+
stateManager.toggleDependencyTypeFilter(action.depType);
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
226
196
|
case 'toggle_info_modal':
|
|
227
197
|
if (!uiState.showInfoModal) {
|
|
228
198
|
// Opening modal - load package info asynchronously
|
|
@@ -275,6 +245,28 @@ class InteractiveUI {
|
|
|
275
245
|
stateManager.setInitialRender(true);
|
|
276
246
|
}
|
|
277
247
|
break;
|
|
248
|
+
case 'toggle_theme_modal':
|
|
249
|
+
stateManager.toggleThemeModal();
|
|
250
|
+
break;
|
|
251
|
+
case 'theme_navigate_up': {
|
|
252
|
+
const themeManager = stateManager.getThemeManager();
|
|
253
|
+
const currentIndex = themes_1.themeNames.indexOf(themeManager.getPreviewTheme());
|
|
254
|
+
const themeArray = Object.keys(themes_1.themes);
|
|
255
|
+
const nextIndex = currentIndex > 0 ? currentIndex - 1 : themeArray.length - 1;
|
|
256
|
+
stateManager.previewTheme(themeArray[nextIndex]);
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
case 'theme_navigate_down': {
|
|
260
|
+
const themeManager = stateManager.getThemeManager();
|
|
261
|
+
const currentIndex = themes_1.themeNames.indexOf(themeManager.getPreviewTheme());
|
|
262
|
+
const themeArray = Object.keys(themes_1.themes);
|
|
263
|
+
const nextIndex = currentIndex < themeArray.length - 1 ? currentIndex + 1 : 0;
|
|
264
|
+
stateManager.previewTheme(themeArray[nextIndex]);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case 'theme_confirm':
|
|
268
|
+
stateManager.confirmTheme();
|
|
269
|
+
break;
|
|
278
270
|
case 'cancel':
|
|
279
271
|
handleCancel();
|
|
280
272
|
return;
|
|
@@ -284,6 +276,8 @@ class InteractiveUI {
|
|
|
284
276
|
}
|
|
285
277
|
};
|
|
286
278
|
const handleConfirm = (selectedStates) => {
|
|
279
|
+
// Reset terminal colors
|
|
280
|
+
process.stdout.write((0, themes_colors_1.getTerminalResetCode)());
|
|
287
281
|
ui_1.CursorUtils.show();
|
|
288
282
|
// Clean up listeners
|
|
289
283
|
if (process.stdin.setRawMode) {
|
|
@@ -295,6 +289,8 @@ class InteractiveUI {
|
|
|
295
289
|
resolve(selectedStates);
|
|
296
290
|
};
|
|
297
291
|
const handleCancel = () => {
|
|
292
|
+
// Reset terminal colors
|
|
293
|
+
process.stdout.write((0, themes_colors_1.getTerminalResetCode)());
|
|
298
294
|
ui_1.CursorUtils.show();
|
|
299
295
|
// Clean up listeners
|
|
300
296
|
if (process.stdin.setRawMode) {
|
|
@@ -309,6 +305,9 @@ class InteractiveUI {
|
|
|
309
305
|
const renderInterface = () => {
|
|
310
306
|
const uiState = stateManager.getUIState();
|
|
311
307
|
const filteredStates = stateManager.getFilteredStates(states);
|
|
308
|
+
// Apply terminal background color
|
|
309
|
+
const bgCode = (0, themes_colors_1.getTerminalBgColorCode)();
|
|
310
|
+
process.stdout.write(bgCode);
|
|
312
311
|
if (uiState.forceFullRender) {
|
|
313
312
|
console.clear();
|
|
314
313
|
ui_1.CursorUtils.hide();
|
|
@@ -316,8 +315,27 @@ class InteractiveUI {
|
|
|
316
315
|
else {
|
|
317
316
|
ui_1.CursorUtils.moveToHome();
|
|
318
317
|
}
|
|
319
|
-
// If modal is open, render only the
|
|
320
|
-
if (uiState.
|
|
318
|
+
// If theme modal is open, render only the theme selector
|
|
319
|
+
if (uiState.showThemeModal) {
|
|
320
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
321
|
+
const terminalHeight = this.getTerminalHeight();
|
|
322
|
+
const themeManager = stateManager.getThemeManager();
|
|
323
|
+
// Render header
|
|
324
|
+
const headerLines = [];
|
|
325
|
+
headerLines.push(' ' + chalk_1.default.bold.magenta('🚀 inup'));
|
|
326
|
+
headerLines.push('');
|
|
327
|
+
headerLines.push(' ' +
|
|
328
|
+
chalk_1.default.bold.white('T ') +
|
|
329
|
+
chalk_1.default.gray('/ Esc Exit theme selector'));
|
|
330
|
+
headerLines.push('');
|
|
331
|
+
headerLines.forEach((line) => console.log(line));
|
|
332
|
+
const modalLines = this.renderer.renderThemeSelectorModal(themeManager.getCurrentTheme(), themeManager.getPreviewTheme(), terminalWidth, terminalHeight);
|
|
333
|
+
modalLines.forEach((line) => console.log(line));
|
|
334
|
+
// Clear any remaining lines from previous render
|
|
335
|
+
ui_1.CursorUtils.clearToEndOfScreen();
|
|
336
|
+
stateManager.markRendered([]);
|
|
337
|
+
}
|
|
338
|
+
else if (uiState.showInfoModal && uiState.infoModalRow >= 0 && uiState.infoModalRow < filteredStates.length) {
|
|
321
339
|
const selectedState = filteredStates[uiState.infoModalRow];
|
|
322
340
|
const terminalWidth = process.stdout.columns || 80;
|
|
323
341
|
const terminalHeight = this.getTerminalHeight();
|
|
@@ -346,10 +364,12 @@ class InteractiveUI {
|
|
|
346
364
|
}
|
|
347
365
|
else {
|
|
348
366
|
// Normal list view (flat rendering - no grouping)
|
|
367
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
368
|
+
const activeFilterLabel = stateManager.getActiveFilterLabel();
|
|
349
369
|
const lines = this.renderer.renderInterface(filteredStates, uiState.currentRow, uiState.scrollOffset, uiState.maxVisibleItems, uiState.forceFullRender, [], // No renderable items - use flat rendering
|
|
350
|
-
|
|
370
|
+
activeFilterLabel, // Show current dependency type filter state
|
|
351
371
|
this.packageManager, // Pass package manager info for header
|
|
352
|
-
uiState.filterMode, uiState.filterQuery, states.length);
|
|
372
|
+
uiState.filterMode, uiState.filterQuery, states.length, terminalWidth);
|
|
353
373
|
// Print all lines
|
|
354
374
|
lines.forEach((line) => console.log(line));
|
|
355
375
|
// Clear any remaining lines from previous render
|
|
@@ -386,6 +406,8 @@ class InteractiveUI {
|
|
|
386
406
|
renderInterface();
|
|
387
407
|
}
|
|
388
408
|
catch (error) {
|
|
409
|
+
// Reset terminal colors
|
|
410
|
+
process.stdout.write((0, themes_colors_1.getTerminalResetCode)());
|
|
389
411
|
// Fallback to simple interface if raw mode fails
|
|
390
412
|
console.log(chalk_1.default.yellow('Raw mode not available, using fallback interface...'));
|
|
391
413
|
resolve(states);
|