inup 1.5.5 → 1.5.6

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.
Files changed (65) hide show
  1. package/README.md +24 -10
  2. package/dist/cli.js +20 -22
  3. package/dist/config/constants.js +4 -2
  4. package/dist/config/package-meta.js +10 -0
  5. package/dist/config/project-config.js +6 -1
  6. package/dist/core/package-detector.js +8 -4
  7. package/dist/core/upgrade-runner.js +7 -10
  8. package/dist/core/upgrader.js +6 -8
  9. package/dist/features/changelog/clients/github-client.js +5 -6
  10. package/dist/features/changelog/services/changelog-service.js +2 -4
  11. package/dist/features/changelog/services/package-metadata-service.js +6 -11
  12. package/dist/features/changelog/services/release-notes-service.js +4 -2
  13. package/dist/features/debug/services/performance-tracker.js +6 -8
  14. package/dist/index.js +1 -2
  15. package/dist/interactive-ui.js +13 -606
  16. package/dist/services/background-audit.js +3 -5
  17. package/dist/services/cache-manager.js +5 -7
  18. package/dist/services/http/inflight.js +22 -0
  19. package/dist/services/http/retry.js +30 -0
  20. package/dist/services/jsdelivr/client.js +191 -0
  21. package/dist/services/jsdelivr/manifest.js +136 -0
  22. package/dist/services/jsdelivr-registry.js +6 -392
  23. package/dist/services/npm-registry.js +12 -81
  24. package/dist/services/persistent-cache.js +8 -13
  25. package/dist/types/domain.js +3 -0
  26. package/dist/types/streaming.js +3 -0
  27. package/dist/types/ui.js +3 -0
  28. package/dist/types.js +17 -0
  29. package/dist/ui/controllers/package-info-modal-controller.js +22 -31
  30. package/dist/ui/controllers/vulnerability-audit-controller.js +17 -8
  31. package/dist/ui/index.js +3 -0
  32. package/dist/ui/input-handler.js +58 -75
  33. package/dist/ui/keymap.js +208 -0
  34. package/dist/ui/modal/package-info-sections/release-notes.js +161 -0
  35. package/dist/ui/modal/package-info-sections/sections.js +150 -0
  36. package/dist/ui/modal/package-info-sections/text.js +75 -0
  37. package/dist/ui/modal/package-info-sections.js +15 -369
  38. package/dist/ui/modal/package-info.js +1 -1
  39. package/dist/ui/renderer/help-modal.js +75 -0
  40. package/dist/ui/renderer/index.js +2 -5
  41. package/dist/ui/renderer/package-list/interface.js +184 -0
  42. package/dist/ui/renderer/package-list/rows.js +172 -0
  43. package/dist/ui/renderer/package-list.js +15 -455
  44. package/dist/ui/session/action-dispatcher.js +233 -0
  45. package/dist/ui/session/index.js +13 -0
  46. package/dist/ui/session/interactive-session.js +280 -0
  47. package/dist/ui/session/selection-state-builder.js +144 -0
  48. package/dist/ui/state/filter-manager.js +17 -6
  49. package/dist/ui/state/modal-manager.js +35 -0
  50. package/dist/ui/state/navigation-manager.js +33 -4
  51. package/dist/ui/state/state-manager.js +68 -3
  52. package/dist/ui/state/theme-manager.js +1 -0
  53. package/dist/ui/themes-colors.js +4 -1
  54. package/dist/ui/themes.js +11 -19
  55. package/dist/ui/utils/cursor.js +3 -4
  56. package/dist/ui/utils/index.js +6 -1
  57. package/dist/ui/utils/text.js +3 -2
  58. package/dist/ui/utils/version.js +60 -86
  59. package/dist/utils/config.js +13 -1
  60. package/dist/utils/filesystem/io.js +87 -0
  61. package/dist/utils/filesystem/paths.js +19 -0
  62. package/dist/utils/filesystem/scan.js +205 -0
  63. package/dist/utils/filesystem.js +17 -335
  64. package/dist/utils/version.js +31 -1
  65. package/package.json +6 -5
@@ -3,15 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FilterManager = void 0;
4
4
  const vulnerability_1 = require("../presenters/vulnerability");
5
5
  class FilterManager {
6
- constructor() {
6
+ state;
7
+ constructor(initial) {
7
8
  this.state = {
8
9
  filterMode: false,
9
10
  filterQuery: '',
10
- showDependencies: true,
11
- showDevDependencies: true,
12
- showPeerDependencies: true,
13
- showOptionalDependencies: true,
14
- showOnlyVulnerable: false,
11
+ showDependencies: initial?.showDependencies ?? true,
12
+ showDevDependencies: initial?.showDevDependencies ?? true,
13
+ showPeerDependencies: initial?.showPeerDependencies ?? true,
14
+ showOptionalDependencies: initial?.showOptionalDependencies ?? true,
15
+ showOnlyVulnerable: initial?.showOnlyVulnerable ?? false,
16
+ };
17
+ }
18
+ /** Snapshot of the persistable filter toggles (no transient search state). */
19
+ getPersistableState() {
20
+ return {
21
+ showDependencies: this.state.showDependencies,
22
+ showDevDependencies: this.state.showDevDependencies,
23
+ showPeerDependencies: this.state.showPeerDependencies,
24
+ showOptionalDependencies: this.state.showOptionalDependencies,
25
+ showOnlyVulnerable: this.state.showOnlyVulnerable,
15
26
  };
16
27
  }
17
28
  getState() {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModalManager = void 0;
4
4
  class ModalManager {
5
+ state;
5
6
  constructor() {
6
7
  this.state = {
7
8
  showInfoModal: false,
@@ -12,6 +13,8 @@ class ModalManager {
12
13
  infoModalTab: 'info',
13
14
  showDebugModal: false,
14
15
  debugModalScrollOffset: 0,
16
+ showHelpModal: false,
17
+ helpModalScrollOffset: 0,
15
18
  };
16
19
  }
17
20
  getInfoModalTab() {
@@ -31,6 +34,38 @@ class ModalManager {
31
34
  this.state.showDebugModal = !this.state.showDebugModal;
32
35
  this.state.debugModalScrollOffset = 0;
33
36
  }
37
+ isHelpModalOpen() {
38
+ return this.state.showHelpModal;
39
+ }
40
+ toggleHelpModal() {
41
+ this.state.showHelpModal = !this.state.showHelpModal;
42
+ this.state.helpModalScrollOffset = 0;
43
+ }
44
+ closeHelpModal() {
45
+ this.state.showHelpModal = false;
46
+ this.state.helpModalScrollOffset = 0;
47
+ }
48
+ scrollHelpModalUp() {
49
+ if (this.state.helpModalScrollOffset > 0) {
50
+ this.state.helpModalScrollOffset--;
51
+ return true;
52
+ }
53
+ return false;
54
+ }
55
+ scrollHelpModalDown(maxOffset) {
56
+ if (this.state.helpModalScrollOffset < maxOffset) {
57
+ this.state.helpModalScrollOffset++;
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+ clampHelpModalScrollOffset(maxOffset) {
63
+ const next = Math.max(0, Math.min(this.state.helpModalScrollOffset, maxOffset));
64
+ if (next === this.state.helpModalScrollOffset)
65
+ return false;
66
+ this.state.helpModalScrollOffset = next;
67
+ return true;
68
+ }
34
69
  closeDebugModal() {
35
70
  this.state.showDebugModal = false;
36
71
  this.state.debugModalScrollOffset = 0;
@@ -2,9 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NavigationManager = void 0;
4
4
  class NavigationManager {
5
+ state;
6
+ renderableItems = [];
7
+ maxVisibleItems;
5
8
  constructor(initialRow = 0, maxVisibleItems = 19) {
6
- this.renderableItems = [];
7
- this.headerLines = 5; // title (with label) + empty + 1 instruction line + status + empty
8
9
  this.state = {
9
10
  currentRow: initialRow,
10
11
  previousRow: -1,
@@ -65,8 +66,6 @@ class NavigationManager {
65
66
  return currentPackageIndex >= totalPackages - 1 ? 0 : currentPackageIndex + 1;
66
67
  }
67
68
  }
68
- // Find current visual index
69
- const currentVisualIndex = this.packageIndexToVisualIndex(currentPackageIndex);
70
69
  // Get all package items with their visual indices
71
70
  const packageItems = [];
72
71
  for (let i = 0; i < this.renderableItems.length; i++) {
@@ -105,6 +104,36 @@ class NavigationManager {
105
104
  this.state.currentRow = this.findNextPackageIndex(this.state.currentRow, 'down', totalItems);
106
105
  this.ensureVisible(this.state.currentRow, totalItems);
107
106
  }
107
+ navigateTop(totalItems) {
108
+ if (totalItems === 0)
109
+ return;
110
+ this.state.previousRow = this.state.currentRow;
111
+ this.state.currentRow = this.firstPackageIndex();
112
+ this.ensureVisible(this.state.currentRow, totalItems);
113
+ }
114
+ navigateBottom(totalItems) {
115
+ if (totalItems === 0)
116
+ return;
117
+ this.state.previousRow = this.state.currentRow;
118
+ this.state.currentRow = this.lastPackageIndex(totalItems);
119
+ this.ensureVisible(this.state.currentRow, totalItems);
120
+ }
121
+ firstPackageIndex() {
122
+ if (this.renderableItems.length === 0)
123
+ return 0;
124
+ const first = this.renderableItems.find((item) => item.type === 'package');
125
+ return first ? first.originalIndex : 0;
126
+ }
127
+ lastPackageIndex(totalPackages) {
128
+ if (this.renderableItems.length === 0)
129
+ return totalPackages - 1;
130
+ for (let i = this.renderableItems.length - 1; i >= 0; i--) {
131
+ const item = this.renderableItems[i];
132
+ if (item.type === 'package')
133
+ return item.originalIndex;
134
+ }
135
+ return totalPackages - 1;
136
+ }
108
137
  ensureVisible(packageIndex, totalPackages) {
109
138
  // Convert package index to visual index for scrolling
110
139
  const visualIndex = this.packageIndexToVisualIndex(packageIndex);
@@ -6,12 +6,19 @@ const modal_manager_1 = require("./modal-manager");
6
6
  const filter_manager_1 = require("./filter-manager");
7
7
  const theme_manager_1 = require("./theme-manager");
8
8
  class StateManager {
9
- constructor(initialRow = 0, terminalHeight = 24) {
10
- this.headerLines = 5; // title (with label) + empty + 1 instruction line + status + empty
9
+ navigationManager;
10
+ modalManager;
11
+ filterManager;
12
+ themeManager;
13
+ displayState;
14
+ renderState;
15
+ notice = null;
16
+ headerLines = 5; // title (with label) + empty + 1 instruction line + status + empty
17
+ constructor(initialRow = 0, terminalHeight = 24, persistedFilters) {
11
18
  const maxVisibleItems = Math.max(5, terminalHeight - this.headerLines - 2);
12
19
  this.navigationManager = new navigation_manager_1.NavigationManager(initialRow, maxVisibleItems);
13
20
  this.modalManager = new modal_manager_1.ModalManager();
14
- this.filterManager = new filter_manager_1.FilterManager();
21
+ this.filterManager = new filter_manager_1.FilterManager(persistedFilters);
15
22
  this.themeManager = new theme_manager_1.ThemeManager();
16
23
  this.displayState = {
17
24
  maxVisibleItems,
@@ -46,12 +53,26 @@ class StateManager {
46
53
  infoModalTab: modalState.infoModalTab,
47
54
  showDebugModal: modalState.showDebugModal,
48
55
  debugModalScrollOffset: modalState.debugModalScrollOffset,
56
+ showHelpModal: modalState.showHelpModal,
57
+ helpModalScrollOffset: modalState.helpModalScrollOffset,
49
58
  filterMode: filterState.filterMode,
50
59
  filterQuery: filterState.filterQuery,
51
60
  showThemeModal: themeState.showThemeModal,
52
61
  currentTheme: themeState.currentTheme,
62
+ notice: this.notice,
53
63
  };
54
64
  }
65
+ // Transient status hint shown once (e.g. "nothing selected"); cleared by the
66
+ // dispatcher on the next action so it never lingers.
67
+ setNotice(message) {
68
+ this.notice = message;
69
+ }
70
+ clearNotice() {
71
+ this.notice = null;
72
+ }
73
+ getNotice() {
74
+ return this.notice;
75
+ }
55
76
  setRenderableItems(items) {
56
77
  this.renderState.renderableItems = items;
57
78
  this.navigationManager.setRenderableItems(items);
@@ -63,6 +84,12 @@ class StateManager {
63
84
  navigateDown(totalItems) {
64
85
  this.navigationManager.navigateDown(totalItems);
65
86
  }
87
+ navigateTop(totalItems) {
88
+ this.navigationManager.navigateTop(totalItems);
89
+ }
90
+ navigateBottom(totalItems) {
91
+ this.navigationManager.navigateBottom(totalItems);
92
+ }
66
93
  packageIndexToVisualIndex(packageIndex) {
67
94
  return this.navigationManager.packageIndexToVisualIndex(packageIndex);
68
95
  }
@@ -152,6 +179,24 @@ class StateManager {
152
179
  }
153
180
  });
154
181
  }
182
+ // Toggle the current row: clear it if selected, otherwise pick the best
183
+ // available update (latest preferred, then range).
184
+ toggleSelection(states) {
185
+ if (states.length === 0)
186
+ return;
187
+ const currentState = states[this.navigationManager.getCurrentRow()];
188
+ if (!currentState || currentState.loadState !== 'ready')
189
+ return;
190
+ if (currentState.selectedOption !== 'none') {
191
+ currentState.selectedOption = 'none';
192
+ }
193
+ else if (currentState.hasMajorUpdate) {
194
+ currentState.selectedOption = 'latest';
195
+ }
196
+ else if (currentState.hasRangeUpdate) {
197
+ currentState.selectedOption = 'range';
198
+ }
199
+ }
155
200
  // Modal delegation
156
201
  toggleInfoModal() {
157
202
  const currentRow = this.navigationManager.getCurrentRow();
@@ -206,6 +251,23 @@ class StateManager {
206
251
  closeDebugModal() {
207
252
  this.modalManager.closeDebugModal();
208
253
  }
254
+ toggleHelpModal() {
255
+ this.modalManager.toggleHelpModal();
256
+ this.renderState.forceFullRender = true;
257
+ }
258
+ closeHelpModal() {
259
+ this.modalManager.closeHelpModal();
260
+ this.renderState.forceFullRender = true;
261
+ }
262
+ scrollHelpModalUp() {
263
+ return this.modalManager.scrollHelpModalUp();
264
+ }
265
+ scrollHelpModalDown(maxOffset) {
266
+ return this.modalManager.scrollHelpModalDown(maxOffset);
267
+ }
268
+ clampHelpModalScrollOffset(maxOffset) {
269
+ return this.modalManager.clampHelpModalScrollOffset(maxOffset);
270
+ }
209
271
  scrollDebugModalUp() {
210
272
  return this.modalManager.scrollDebugModalUp();
211
273
  }
@@ -264,6 +326,9 @@ class StateManager {
264
326
  getActiveFilterLabel() {
265
327
  return this.filterManager.getActiveFilterLabel();
266
328
  }
329
+ getFilterSnapshot() {
330
+ return this.filterManager.getPersistableState();
331
+ }
267
332
  // Display and render state management
268
333
  updateTerminalHeight(newHeight) {
269
334
  const newMaxVisibleItems = Math.max(5, newHeight - this.headerLines - 2);
@@ -8,6 +8,7 @@ const config_1 = require("../../utils/config");
8
8
  // Global theme state for renderers to access
9
9
  let globalCurrentTheme = themes_1.defaultTheme;
10
10
  class ThemeManager {
11
+ state;
11
12
  constructor() {
12
13
  // Load saved theme from config, fallback to default
13
14
  const savedTheme = config_1.configManager.getTheme();
@@ -11,6 +11,7 @@ exports.getTerminalResetCode = getTerminalResetCode;
11
11
  exports.coloredInupLogo = coloredInupLogo;
12
12
  const chalk_1 = __importDefault(require("chalk"));
13
13
  const theme_manager_1 = require("./state/theme-manager");
14
+ const config_1 = require("../config");
14
15
  // Centralized theme color definitions - single source of truth
15
16
  const themeColorDefinitions = {
16
17
  default: {
@@ -196,7 +197,9 @@ function getTerminalResetCode() {
196
197
  }
197
198
  const BRAND_COLORS = [chalk_1.default.red, chalk_1.default.yellow, chalk_1.default.blue, chalk_1.default.magenta];
198
199
  function coloredInupLogo() {
199
- return BRAND_COLORS.map((color, i) => color.bold('inup'[i])).join('');
200
+ return Array.from(config_1.PACKAGE_NAME)
201
+ .map((ch, i) => BRAND_COLORS[i % BRAND_COLORS.length].bold(ch))
202
+ .join('');
200
203
  }
201
204
  exports.themeColors = {
202
205
  primary: () => getThemeColor('primary'),
package/dist/ui/themes.js CHANGED
@@ -5,26 +5,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.themeNames = exports.defaultTheme = exports.themes = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
- const themesMetadata = {
9
- default: 'Default',
10
- catppuccin: 'Catppuccin',
11
- dracula: 'Dracula',
12
- vsc: 'VS Code',
13
- monokai: 'Monokai',
14
- tokyonight: 'Tokyo Night',
15
- onedark: 'One Dark',
16
- gruvbox: 'Gruvbox',
17
- solarized: 'Solarized',
18
- github: 'GitHub',
8
+ exports.themes = {
9
+ default: { name: 'Default', colors: chalk_1.default },
10
+ catppuccin: { name: 'Catppuccin', colors: chalk_1.default },
11
+ dracula: { name: 'Dracula', colors: chalk_1.default },
12
+ vsc: { name: 'VS Code', colors: chalk_1.default },
13
+ monokai: { name: 'Monokai', colors: chalk_1.default },
14
+ tokyonight: { name: 'Tokyo Night', colors: chalk_1.default },
15
+ onedark: { name: 'One Dark', colors: chalk_1.default },
16
+ gruvbox: { name: 'Gruvbox', colors: chalk_1.default },
17
+ solarized: { name: 'Solarized', colors: chalk_1.default },
18
+ github: { name: 'GitHub', colors: chalk_1.default },
19
19
  };
20
- // Theme definitions
21
- exports.themes = Object.entries(themesMetadata).reduce((acc, [key, name]) => {
22
- acc[key] = {
23
- name,
24
- colors: chalk_1.default,
25
- };
26
- return acc;
27
- }, {});
28
20
  exports.defaultTheme = 'default';
29
21
  exports.themeNames = Object.keys(exports.themes);
30
22
  //# sourceMappingURL=themes.js.map
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
- /**
3
- * Cursor and terminal utility functions
4
- */
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ConsoleUtils = exports.CursorUtils = void 0;
3
+ exports.ConsoleUtils = exports.CursorUtils = exports.RAW_SHOW_CURSOR = exports.RAW_EXIT_ALT_SCREEN = void 0;
4
+ exports.RAW_EXIT_ALT_SCREEN = '\x1b[?1049l';
5
+ exports.RAW_SHOW_CURSOR = '\x1b[?25h';
7
6
  exports.CursorUtils = {
8
7
  /**
9
8
  * Switch to the terminal alternate screen buffer.
@@ -1,11 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wrapPlainText = exports.truncatePlainText = exports.stripAnsi = exports.getVisualLength = exports.TerminalInput = exports.ConsoleUtils = exports.CursorUtils = exports.VersionUtils = void 0;
3
+ exports.wrapPlainText = exports.truncatePlainText = exports.stripAnsi = exports.getVisualLength = exports.TerminalInput = exports.RAW_SHOW_CURSOR = exports.RAW_EXIT_ALT_SCREEN = exports.ConsoleUtils = exports.CursorUtils = exports.formatVersionDiff = exports.truncateMiddle = exports.applyVersionPrefix = exports.VersionUtils = void 0;
4
4
  var version_1 = require("./version");
5
5
  Object.defineProperty(exports, "VersionUtils", { enumerable: true, get: function () { return version_1.VersionUtils; } });
6
+ Object.defineProperty(exports, "applyVersionPrefix", { enumerable: true, get: function () { return version_1.applyVersionPrefix; } });
7
+ Object.defineProperty(exports, "truncateMiddle", { enumerable: true, get: function () { return version_1.truncateMiddle; } });
8
+ Object.defineProperty(exports, "formatVersionDiff", { enumerable: true, get: function () { return version_1.formatVersionDiff; } });
6
9
  var cursor_1 = require("./cursor");
7
10
  Object.defineProperty(exports, "CursorUtils", { enumerable: true, get: function () { return cursor_1.CursorUtils; } });
8
11
  Object.defineProperty(exports, "ConsoleUtils", { enumerable: true, get: function () { return cursor_1.ConsoleUtils; } });
12
+ Object.defineProperty(exports, "RAW_EXIT_ALT_SCREEN", { enumerable: true, get: function () { return cursor_1.RAW_EXIT_ALT_SCREEN; } });
13
+ Object.defineProperty(exports, "RAW_SHOW_CURSOR", { enumerable: true, get: function () { return cursor_1.RAW_SHOW_CURSOR; } });
9
14
  var terminal_input_1 = require("./terminal-input");
10
15
  Object.defineProperty(exports, "TerminalInput", { enumerable: true, get: function () { return terminal_input_1.TerminalInput; } });
11
16
  var text_1 = require("./text");
@@ -4,9 +4,10 @@ exports.stripAnsi = stripAnsi;
4
4
  exports.getVisualLength = getVisualLength;
5
5
  exports.truncatePlainText = truncatePlainText;
6
6
  exports.wrapPlainText = wrapPlainText;
7
- const version_1 = require("./version");
7
+ const ANSI_PATTERN = /\[[0-9;?]*[ -/]*[@-~]/g;
8
+ const OSC8_PATTERN = /]8;;.*?(?:|\\)|]8;;(?:|\\)/g;
8
9
  function stripAnsi(text) {
9
- return version_1.VersionUtils.stripAnsi(text);
10
+ return text.replace(OSC8_PATTERN, '').replace(ANSI_PATTERN, '');
10
11
  }
11
12
  function getVisualLength(text) {
12
13
  const cleaned = stripAnsi(text);
@@ -3,100 +3,74 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.VersionUtils = void 0;
6
+ exports.VersionUtils = exports.getVisualLength = exports.stripAnsi = void 0;
7
+ exports.applyVersionPrefix = applyVersionPrefix;
8
+ exports.truncateMiddle = truncateMiddle;
9
+ exports.formatVersionDiff = formatVersionDiff;
7
10
  const chalk_1 = __importDefault(require("chalk"));
8
- /**
9
- * ANSI escape code pattern for stripping terminal colors
10
- */
11
- const ANSI_PATTERN = /\u001b\[[0-9;?]*[ -/]*[@-~]/g;
12
- const OSC8_PATTERN = /\u001b]8;;.*?(?:\u0007|\u001b\\)|\u001b]8;;(?:\u0007|\u001b\\)/g;
13
- class VersionUtils {
14
- static applyVersionPrefix(originalSpecifier, targetVersion) {
15
- // Extract prefix from original specifier (^ or ~)
16
- const prefixMatch = originalSpecifier.match(/^([^\d]+)/);
17
- const prefix = prefixMatch ? prefixMatch[1] : '';
18
- // Return target version with same prefix
19
- return prefix + targetVersion;
20
- }
21
- /**
22
- * Strip ANSI escape codes from a string
23
- */
24
- static stripAnsi(str) {
25
- return str.replace(OSC8_PATTERN, '').replace(ANSI_PATTERN, '');
11
+ const text_1 = require("./text");
12
+ Object.defineProperty(exports, "stripAnsi", { enumerable: true, get: function () { return text_1.stripAnsi; } });
13
+ Object.defineProperty(exports, "getVisualLength", { enumerable: true, get: function () { return text_1.getVisualLength; } });
14
+ function applyVersionPrefix(originalSpecifier, targetVersion) {
15
+ const prefixMatch = originalSpecifier.match(/^([^\d]+)/);
16
+ const prefix = prefixMatch ? prefixMatch[1] : '';
17
+ return prefix + targetVersion;
18
+ }
19
+ function truncateMiddle(str, maxLength) {
20
+ const visualLength = (0, text_1.getVisualLength)(str);
21
+ if (visualLength <= maxLength) {
22
+ return str;
26
23
  }
27
- /**
28
- * Get the visual length of a string (excluding ANSI codes)
29
- */
30
- static getVisualLength(str) {
31
- return VersionUtils.stripAnsi(str).length;
24
+ const ellipsis = '…';
25
+ const availableLength = maxLength - 1;
26
+ const startLength = Math.ceil(availableLength / 2);
27
+ const endLength = Math.floor(availableLength / 2);
28
+ const rawText = (0, text_1.stripAnsi)(str);
29
+ const start = rawText.substring(0, startLength);
30
+ const end = rawText.substring(rawText.length - endLength);
31
+ return start + ellipsis + end;
32
+ }
33
+ function formatVersionDiff(current, target, colorFn) {
34
+ if (current === target) {
35
+ return chalk_1.default.white(target);
32
36
  }
33
- /**
34
- * Truncate text with ellipsis in the middle if it exceeds maxLength
35
- * Preserves ANSI color codes and applies them to the ellipsis
36
- * @param str The text to truncate (may contain ANSI codes)
37
- * @param maxLength The maximum visual length
38
- * @returns Truncated text with middle ellipsis if needed
39
- */
40
- static truncateMiddle(str, maxLength) {
41
- const visualLength = this.getVisualLength(str);
42
- if (visualLength <= maxLength) {
43
- return str;
37
+ const currentParts = current.split('.').map((part) => parseInt(part) || 0);
38
+ const targetParts = target.split('.').map((part) => parseInt(part) || 0);
39
+ let firstDiffSegment = -1;
40
+ const maxLength = Math.max(currentParts.length, targetParts.length);
41
+ for (let i = 0; i < maxLength; i++) {
42
+ const currentPart = currentParts[i] || 0;
43
+ const targetPart = targetParts[i] || 0;
44
+ if (currentPart !== targetPart) {
45
+ firstDiffSegment = i;
46
+ break;
44
47
  }
45
- // Need to truncate with ellipsis in the middle
46
- const ellipsis = '…';
47
- const availableLength = maxLength - 1; // Reserve 1 char for ellipsis
48
- const startLength = Math.ceil(availableLength / 2);
49
- const endLength = Math.floor(availableLength / 2);
50
- // Extract raw text without ANSI codes to calculate positions
51
- const rawText = VersionUtils.stripAnsi(str);
52
- const start = rawText.substring(0, startLength);
53
- const end = rawText.substring(rawText.length - endLength);
54
- return start + ellipsis + end;
55
48
  }
56
- static formatVersionDiff(current, target, colorFn) {
57
- if (current === target) {
58
- return chalk_1.default.white(target);
59
- }
60
- // Parse semantic versions into parts
61
- const currentParts = current.split('.').map((part) => parseInt(part) || 0);
62
- const targetParts = target.split('.').map((part) => parseInt(part) || 0);
63
- // Find the first differing version segment (major, minor, or patch)
64
- let firstDiffSegment = -1;
65
- const maxLength = Math.max(currentParts.length, targetParts.length);
66
- for (let i = 0; i < maxLength; i++) {
67
- const currentPart = currentParts[i] || 0;
68
- const targetPart = targetParts[i] || 0;
69
- if (currentPart !== targetPart) {
70
- firstDiffSegment = i;
71
- break;
72
- }
49
+ if (firstDiffSegment === -1) {
50
+ return chalk_1.default.white(target);
51
+ }
52
+ const result = [];
53
+ for (let i = 0; i < maxLength; i++) {
54
+ const targetPart = targetParts[i] || 0;
55
+ const partStr = targetPart.toString();
56
+ if (i < firstDiffSegment) {
57
+ result.push(partStr);
73
58
  }
74
- if (firstDiffSegment === -1) {
75
- // Versions are identical (shouldn't happen due to guard above, but just in case)
76
- return chalk_1.default.white(target);
59
+ else {
60
+ result.push(colorFn(partStr));
77
61
  }
78
- // Build the result with proper coloring
79
- const result = [];
80
- for (let i = 0; i < maxLength; i++) {
81
- const targetPart = targetParts[i] || 0;
82
- const partStr = targetPart.toString();
83
- if (i < firstDiffSegment) {
84
- // Unchanged segment - keep white
85
- result.push(partStr);
86
- }
87
- else {
88
- // Changed segment or later - apply color
89
- result.push(colorFn(partStr));
90
- }
91
- // Add dot separator if not the last part
92
- if (i < maxLength - 1) {
93
- // Color the dot the same as the following part
94
- const nextPartColor = i + 1 < firstDiffSegment ? chalk_1.default.white : colorFn;
95
- result.push(nextPartColor('.'));
96
- }
62
+ if (i < maxLength - 1) {
63
+ const nextPartColor = i + 1 < firstDiffSegment ? chalk_1.default.white : colorFn;
64
+ result.push(nextPartColor('.'));
97
65
  }
98
- return result.join('');
99
66
  }
67
+ return result.join('');
100
68
  }
101
- exports.VersionUtils = VersionUtils;
69
+ exports.VersionUtils = {
70
+ applyVersionPrefix,
71
+ truncateMiddle,
72
+ formatVersionDiff,
73
+ stripAnsi: text_1.stripAnsi,
74
+ getVisualLength: text_1.getVisualLength,
75
+ };
102
76
  //# sourceMappingURL=version.js.map
@@ -7,11 +7,14 @@ exports.configManager = void 0;
7
7
  const fs_1 = require("fs");
8
8
  const path_1 = require("path");
9
9
  const env_paths_1 = __importDefault(require("env-paths"));
10
+ const config_1 = require("../config");
10
11
  class ConfigManager {
12
+ configDir;
13
+ configPath;
11
14
  constructor() {
12
15
  // Use env-paths for cross-platform config directory support
13
16
  // Mac/Linux: ~/.config/inup, Windows: %APPDATA%/inup
14
- const paths = (0, env_paths_1.default)('inup');
17
+ const paths = (0, env_paths_1.default)(config_1.PACKAGE_NAME);
15
18
  this.configDir = paths.config;
16
19
  this.configPath = (0, path_1.join)(this.configDir, 'config.json');
17
20
  }
@@ -51,6 +54,15 @@ class ConfigManager {
51
54
  config.theme = theme;
52
55
  this.writeConfig(config);
53
56
  }
57
+ getFilters() {
58
+ const config = this.readConfig();
59
+ return config.filters ?? null;
60
+ }
61
+ setFilters(filters) {
62
+ const config = this.readConfig();
63
+ config.filters = filters;
64
+ this.writeConfig(config);
65
+ }
54
66
  }
55
67
  // Export singleton instance
56
68
  exports.configManager = new ConfigManager();
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readPackageJson = readPackageJson;
4
+ exports.readPackageJsonAsync = readPackageJsonAsync;
5
+ exports.collectAllDependencies = collectAllDependencies;
6
+ exports.collectAllDependenciesAsync = collectAllDependenciesAsync;
7
+ const fs_1 = require("fs");
8
+ const fs_2 = require("fs");
9
+ function readPackageJson(path) {
10
+ try {
11
+ const content = (0, fs_1.readFileSync)(path, 'utf-8');
12
+ return JSON.parse(content);
13
+ }
14
+ catch (error) {
15
+ throw new Error(`Failed to read package.json: ${error}`);
16
+ }
17
+ }
18
+ async function readPackageJsonAsync(path) {
19
+ try {
20
+ const content = await fs_2.promises.readFile(path, 'utf-8');
21
+ return JSON.parse(content);
22
+ }
23
+ catch (error) {
24
+ throw new Error(`Failed to read package.json: ${error}`);
25
+ }
26
+ }
27
+ function collectAllDependencies(packageJsonFiles, _options = {}) {
28
+ const allDeps = [];
29
+ for (const packageJsonPath of packageJsonFiles) {
30
+ try {
31
+ const packageJson = readPackageJson(packageJsonPath);
32
+ const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
33
+ for (const depType of depTypes) {
34
+ const deps = packageJson[depType];
35
+ if (deps && typeof deps === 'object') {
36
+ for (const [name, version] of Object.entries(deps)) {
37
+ allDeps.push({
38
+ name,
39
+ version: version,
40
+ type: depType,
41
+ packageJsonPath,
42
+ });
43
+ }
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ // Skip malformed package.json files
49
+ }
50
+ }
51
+ return allDeps;
52
+ }
53
+ async function collectAllDependenciesAsync(packageJsonFiles, _options = {}) {
54
+ const packageJsonPromises = packageJsonFiles.map(async (packageJsonPath) => {
55
+ try {
56
+ const packageJson = await readPackageJsonAsync(packageJsonPath);
57
+ return { packageJson, packageJsonPath };
58
+ }
59
+ catch {
60
+ // Skip malformed package.json files
61
+ return null;
62
+ }
63
+ });
64
+ const results = await Promise.all(packageJsonPromises);
65
+ const allDeps = [];
66
+ for (const result of results) {
67
+ if (!result)
68
+ continue;
69
+ const { packageJson, packageJsonPath } = result;
70
+ const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
71
+ for (const depType of depTypes) {
72
+ const deps = packageJson[depType];
73
+ if (deps && typeof deps === 'object') {
74
+ for (const [name, version] of Object.entries(deps)) {
75
+ allDeps.push({
76
+ name,
77
+ version: version,
78
+ type: depType,
79
+ packageJsonPath,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return allDeps;
86
+ }
87
+ //# sourceMappingURL=io.js.map