inup 1.5.4 → 1.5.5
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/interactive-ui.js
CHANGED
|
@@ -470,8 +470,18 @@ class InteractiveUI {
|
|
|
470
470
|
}
|
|
471
471
|
process.stdout.write(lines.map((line) => applyBackgroundToLine(line, bgCode)).join('\n'));
|
|
472
472
|
};
|
|
473
|
+
const key = (text) => chalk_1.default.bold.white(text);
|
|
474
|
+
const hint = (text) => chalk_1.default.gray(text);
|
|
475
|
+
const sep = hint(' · ');
|
|
476
|
+
const SHORTCUTS = {
|
|
477
|
+
scroll: key('↑/↓ ') + hint('Scroll'),
|
|
478
|
+
version: key('←/→ ') + hint('Version'),
|
|
479
|
+
switchTab: key('Tab ') + hint('Switch tab'),
|
|
480
|
+
closeInfo: key('I / Esc ') + hint('Close'),
|
|
481
|
+
closeTheme: key('T / Esc ') + hint('Close'),
|
|
482
|
+
};
|
|
473
483
|
const buildModalHeaderLines = (shortcutLabel) => [
|
|
474
|
-
' ' + chalk_1.default.bold
|
|
484
|
+
' ' + chalk_1.default.bold('🚀 ') + (0, themes_colors_1.coloredInupLogo)(),
|
|
475
485
|
'',
|
|
476
486
|
' ' + shortcutLabel,
|
|
477
487
|
'',
|
|
@@ -503,11 +513,24 @@ class InteractiveUI {
|
|
|
503
513
|
process.off('SIGWINCH', handleResize);
|
|
504
514
|
this.refreshView = undefined;
|
|
505
515
|
};
|
|
516
|
+
// Safety net: restore terminal if the process exits without going through finalizeSelection.
|
|
517
|
+
// Only synchronous writes work in an 'exit' handler, but that's all we need here.
|
|
518
|
+
const emergencyCleanup = () => {
|
|
519
|
+
if (ownsAlternateScreen) {
|
|
520
|
+
process.stdout.write('\x1b[?1049l');
|
|
521
|
+
}
|
|
522
|
+
process.stdout.write('\x1b[?25h');
|
|
523
|
+
if (process.stdin.setRawMode) {
|
|
524
|
+
process.stdin.setRawMode(false);
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
process.on('exit', emergencyCleanup);
|
|
506
528
|
const finalizeSelection = (selectedStates) => {
|
|
507
529
|
isResolved = true;
|
|
508
530
|
this.packageInfoModalController.cancel();
|
|
509
531
|
releaseInteractiveScreen();
|
|
510
532
|
cleanupInteractiveSession();
|
|
533
|
+
process.off('exit', emergencyCleanup);
|
|
511
534
|
resolve(selectedStates);
|
|
512
535
|
};
|
|
513
536
|
const renderInterface = () => {
|
|
@@ -530,7 +553,7 @@ class InteractiveUI {
|
|
|
530
553
|
const terminalHeight = this.getTerminalHeight();
|
|
531
554
|
const themeManager = stateManager.getThemeManager();
|
|
532
555
|
const modalLines = this.renderer.renderThemeSelectorModal(themeManager.getCurrentTheme(), themeManager.getPreviewTheme(), terminalWidth, terminalHeight);
|
|
533
|
-
renderModalViewport('theme-modal',
|
|
556
|
+
renderModalViewport('theme-modal', SHORTCUTS.closeTheme, modalLines, terminalWidth, terminalHeight, bgCode);
|
|
534
557
|
}
|
|
535
558
|
else if (uiState.showDebugModal) {
|
|
536
559
|
const terminalWidth = process.stdout.columns || 80;
|
|
@@ -539,10 +562,11 @@ class InteractiveUI {
|
|
|
539
562
|
const result = (0, debug_1.renderPerformanceModal)(snapshot, terminalWidth, Math.max(8, terminalHeight - 4), uiState.debugModalScrollOffset);
|
|
540
563
|
debugModalMaxScrollOffset = result.maxScrollOffset;
|
|
541
564
|
stateManager.clampDebugModalScrollOffset(debugModalMaxScrollOffset);
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
565
|
+
const debugHints = [
|
|
566
|
+
result.usesInternalScroll && result.maxScrollOffset > 0 ? SHORTCUTS.scroll : '',
|
|
567
|
+
SHORTCUTS.closeInfo,
|
|
568
|
+
].filter(Boolean).join(sep);
|
|
569
|
+
renderModalViewport('info-modal', debugHints, result.lines, terminalWidth, terminalHeight, bgCode);
|
|
546
570
|
}
|
|
547
571
|
else if (uiState.showInfoModal &&
|
|
548
572
|
uiState.infoModalRow >= 0 &&
|
|
@@ -554,7 +578,7 @@ class InteractiveUI {
|
|
|
554
578
|
// Show loading state
|
|
555
579
|
const result = this.renderer.renderPackageInfoLoading(selectedState, terminalWidth, Math.max(8, terminalHeight - 4));
|
|
556
580
|
infoModalMaxScrollOffset = result.maxScrollOffset;
|
|
557
|
-
renderModalViewport('info-modal',
|
|
581
|
+
renderModalViewport('info-modal', SHORTCUTS.closeInfo, result.lines, terminalWidth, terminalHeight, bgCode);
|
|
558
582
|
}
|
|
559
583
|
else {
|
|
560
584
|
// Show full info with scroll support
|
|
@@ -562,18 +586,13 @@ class InteractiveUI {
|
|
|
562
586
|
const result = this.renderer.renderPackageInfoModal(selectedState, terminalWidth, Math.max(8, terminalHeight - 4), uiState.infoModalScrollOffset, activeTab);
|
|
563
587
|
infoModalMaxScrollOffset = result.maxScrollOffset;
|
|
564
588
|
stateManager.clampInfoModalScrollOffset(infoModalMaxScrollOffset);
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
: ''
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
renderModalViewport('info-modal',
|
|
572
|
-
versionHint +
|
|
573
|
-
chalk_1.default.bold.white('Tab ') +
|
|
574
|
-
chalk_1.default.gray('Switch tab · ') +
|
|
575
|
-
chalk_1.default.bold.white('I / Esc ') +
|
|
576
|
-
chalk_1.default.gray('Exit this view'), result.lines, terminalWidth, terminalHeight, bgCode);
|
|
589
|
+
const hints = [
|
|
590
|
+
result.usesInternalScroll && result.maxScrollOffset > 0 ? SHORTCUTS.scroll : '',
|
|
591
|
+
activeTab === 'info' ? SHORTCUTS.version : '',
|
|
592
|
+
SHORTCUTS.switchTab,
|
|
593
|
+
SHORTCUTS.closeInfo,
|
|
594
|
+
].filter(Boolean).join(sep);
|
|
595
|
+
renderModalViewport('info-modal', hints, result.lines, terminalWidth, terminalHeight, bgCode);
|
|
577
596
|
}
|
|
578
597
|
}
|
|
579
598
|
else {
|
|
@@ -631,6 +650,7 @@ class InteractiveUI {
|
|
|
631
650
|
this.enqueueSecurityAudit(states);
|
|
632
651
|
}
|
|
633
652
|
catch (error) {
|
|
653
|
+
process.off('exit', emergencyCleanup);
|
|
634
654
|
releaseInteractiveScreen();
|
|
635
655
|
// Reset terminal colors
|
|
636
656
|
process.stdout.write((0, themes_colors_1.getTerminalResetCode)());
|
|
@@ -651,7 +671,22 @@ class InteractiveUI {
|
|
|
651
671
|
cleanupConfirmationSession();
|
|
652
672
|
resolve(confirmed);
|
|
653
673
|
};
|
|
654
|
-
|
|
674
|
+
// Safety net for the same reason as selectPackages — synchronous restore on exit.
|
|
675
|
+
// The confirmation screen does not enter the alternate screen, so alt-screen
|
|
676
|
+
// restoration is intentionally omitted here. If that ever changes, mirror the
|
|
677
|
+
// ownsAlternateScreen-gated pattern from selectPackages.
|
|
678
|
+
const confirmEmergencyCleanup = () => {
|
|
679
|
+
process.stdout.write('\x1b[?25h');
|
|
680
|
+
if (process.stdin.setRawMode) {
|
|
681
|
+
process.stdin.setRawMode(false);
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
process.on('exit', confirmEmergencyCleanup);
|
|
685
|
+
const handleConfirmWithCleanup = (confirmed) => {
|
|
686
|
+
handleConfirm(confirmed);
|
|
687
|
+
process.off('exit', confirmEmergencyCleanup);
|
|
688
|
+
};
|
|
689
|
+
const inputHandler = new ui_1.ConfirmationInputHandler(handleConfirmWithCleanup);
|
|
655
690
|
const keypressHandler = (str, key) => inputHandler.handleKeypress(str, key);
|
|
656
691
|
// Setup keypress handling
|
|
657
692
|
try {
|
|
@@ -663,6 +698,7 @@ class InteractiveUI {
|
|
|
663
698
|
ui_1.CursorUtils.hide();
|
|
664
699
|
}
|
|
665
700
|
catch (error) {
|
|
701
|
+
process.off('exit', confirmEmergencyCleanup);
|
|
666
702
|
ui_1.TerminalInput.promptForConfirmation('Proceed with upgrade? [Y/n] ')
|
|
667
703
|
.then(resolve)
|
|
668
704
|
.catch(() => resolve(false));
|
package/dist/ui/input-handler.js
CHANGED
|
@@ -15,7 +15,7 @@ class InputHandler {
|
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
if (key && key.ctrl && key.name === 'c') {
|
|
18
|
-
|
|
18
|
+
this.onCancel();
|
|
19
19
|
process.exit(0);
|
|
20
20
|
}
|
|
21
21
|
const uiState = this.stateManager.getUIState();
|
|
@@ -267,7 +267,9 @@ class ConfirmationInputHandler {
|
|
|
267
267
|
return;
|
|
268
268
|
}
|
|
269
269
|
if (key && key.ctrl && key.name === 'c') {
|
|
270
|
-
|
|
270
|
+
// onConfirm runs the normal cleanup path (cursor show, raw-mode off, listener
|
|
271
|
+
// removal). The 'exit' listener registered by confirmUpgrade is a final backstop.
|
|
272
|
+
this.onConfirm(false);
|
|
271
273
|
process.exit(0);
|
|
272
274
|
}
|
|
273
275
|
if (!key) {
|
|
@@ -281,7 +281,8 @@ function buildUsedBySections(state, modalWidth) {
|
|
|
281
281
|
];
|
|
282
282
|
}
|
|
283
283
|
function buildPackageInfoSections(state, modalWidth, activeTab) {
|
|
284
|
-
const title = chalk_1.default.
|
|
284
|
+
const title = chalk_1.default.bold('Package: ') +
|
|
285
|
+
(0, themes_colors_1.getThemeColor)('packageName')(state.name) +
|
|
285
286
|
buildTabBarSuffix(activeTab, getUsedByPaths(state).length);
|
|
286
287
|
const authorLicense = chalk_1.default.gray(`${state.author || 'Unknown'} • ${state.license || 'MIT'}`);
|
|
287
288
|
const currentVersion = chalk_1.default.yellow(state.currentVersionSpecifier);
|
|
@@ -223,12 +223,10 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
223
223
|
};
|
|
224
224
|
const pmColor = colorMap[packageManager.name] || packageManager.color;
|
|
225
225
|
// Each character in "inup" gets a different color
|
|
226
|
-
const inupColors = [chalk_1.default.red, chalk_1.default.yellow, chalk_1.default.blue, chalk_1.default.magenta];
|
|
227
|
-
const coloredInup = inupColors.map((color, i) => color.bold('inup'[i])).join('');
|
|
228
226
|
const headerLine = ' ' +
|
|
229
227
|
chalk_1.default.bold(pmColor('🚀')) +
|
|
230
228
|
' ' +
|
|
231
|
-
|
|
229
|
+
(0, themes_colors_1.coloredInupLogo)() +
|
|
232
230
|
(0, themes_colors_1.getThemeColor)('textSecondary')(` (${packageManager.displayName})`);
|
|
233
231
|
// Show filter state (always show, including "All")
|
|
234
232
|
const fullHeaderLine = activeFilterLabel
|
|
@@ -241,12 +239,7 @@ function renderInterface(states, currentRow, scrollOffset, maxVisibleItems, forc
|
|
|
241
239
|
output.push(fullHeaderLine + ' '.repeat(headerPadding));
|
|
242
240
|
}
|
|
243
241
|
else {
|
|
244
|
-
const headerLine = ' ' +
|
|
245
|
-
chalk_1.default.bold.blue('🚀 ') +
|
|
246
|
-
chalk_1.default.bold.red('i') +
|
|
247
|
-
chalk_1.default.bold.yellow('n') +
|
|
248
|
-
chalk_1.default.bold.blue('u') +
|
|
249
|
-
chalk_1.default.bold.magenta('p');
|
|
242
|
+
const headerLine = ' ' + chalk_1.default.bold.blue('🚀 ') + (0, themes_colors_1.coloredInupLogo)();
|
|
250
243
|
// Show filter state (always show, including "All")
|
|
251
244
|
const fullHeaderLine = activeFilterLabel
|
|
252
245
|
? headerLine +
|
package/dist/ui/themes-colors.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.getThemeColor = getThemeColor;
|
|
|
8
8
|
exports.getThemeBgColor = getThemeBgColor;
|
|
9
9
|
exports.getTerminalBgColorCode = getTerminalBgColorCode;
|
|
10
10
|
exports.getTerminalResetCode = getTerminalResetCode;
|
|
11
|
+
exports.coloredInupLogo = coloredInupLogo;
|
|
11
12
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
13
|
const theme_manager_1 = require("./state/theme-manager");
|
|
13
14
|
// Centralized theme color definitions - single source of truth
|
|
@@ -193,6 +194,10 @@ function getTerminalBgColorCode() {
|
|
|
193
194
|
function getTerminalResetCode() {
|
|
194
195
|
return '\x1b[0m';
|
|
195
196
|
}
|
|
197
|
+
const BRAND_COLORS = [chalk_1.default.red, chalk_1.default.yellow, chalk_1.default.blue, chalk_1.default.magenta];
|
|
198
|
+
function coloredInupLogo() {
|
|
199
|
+
return BRAND_COLORS.map((color, i) => color.bold('inup'[i])).join('');
|
|
200
|
+
}
|
|
196
201
|
exports.themeColors = {
|
|
197
202
|
primary: () => getThemeColor('primary'),
|
|
198
203
|
secondary: () => getThemeColor('secondary'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inup",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.5",
|
|
4
4
|
"description": "Interactive dependency upgrader for npm, yarn, pnpm & bun. Zero-config, monorepo-ready. Upgrade-interactive for every package manager.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -43,20 +43,20 @@
|
|
|
43
43
|
"README.md"
|
|
44
44
|
],
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^24.12.
|
|
46
|
+
"@types/node": "^24.12.4",
|
|
47
47
|
"@types/semver": "^7.7.1",
|
|
48
|
-
"@vitest/coverage-v8": "^4.1.
|
|
49
|
-
"prettier": "^3.8.
|
|
50
|
-
"typescript": "^6.0.
|
|
51
|
-
"vitest": "^4.1.
|
|
48
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
49
|
+
"prettier": "^3.8.3",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"vitest": "^4.1.6"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"chalk": "^5.6.2",
|
|
55
55
|
"commander": "^14.0.3",
|
|
56
56
|
"env-paths": "^4.0.0",
|
|
57
57
|
"nanospinner": "^1.2.2",
|
|
58
|
-
"semver": "^7.
|
|
59
|
-
"undici": "^8.
|
|
58
|
+
"semver": "^7.8.0",
|
|
59
|
+
"undici": "^8.3.0"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=20.0.0"
|