inup 1.4.12 → 1.5.1

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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -30
  3. package/dist/cli.js +29 -14
  4. package/dist/config/project-config.js +6 -0
  5. package/dist/core/package-detector.js +3 -2
  6. package/dist/core/upgrade-runner.js +6 -3
  7. package/dist/features/changelog/clients/github-client.js +134 -0
  8. package/dist/features/changelog/clients/npm-registry-client.js +53 -0
  9. package/dist/features/changelog/index.js +19 -0
  10. package/dist/features/changelog/parsers/changelog-parser.js +68 -0
  11. package/dist/features/changelog/parsers/github-release-html-parser.js +61 -0
  12. package/dist/features/changelog/parsers/package-metadata.js +34 -0
  13. package/dist/features/changelog/parsers/repository-ref.js +26 -0
  14. package/dist/features/changelog/services/changelog-service.js +30 -0
  15. package/dist/features/changelog/services/package-metadata-service.js +108 -0
  16. package/dist/features/changelog/services/release-notes-service.js +180 -0
  17. package/dist/features/changelog/types/changelog.types.js +3 -0
  18. package/dist/interactive-ui.js +242 -114
  19. package/dist/services/background-audit.js +60 -0
  20. package/dist/services/index.js +3 -1
  21. package/dist/services/vulnerability-checker.js +133 -0
  22. package/dist/ui/controllers/index.js +8 -0
  23. package/dist/ui/controllers/package-info-modal-controller.js +237 -0
  24. package/dist/ui/controllers/vulnerability-audit-controller.js +82 -0
  25. package/dist/ui/index.js +3 -0
  26. package/dist/ui/input-handler.js +40 -9
  27. package/dist/ui/modal/index.js +22 -0
  28. package/dist/ui/modal/layout.js +84 -0
  29. package/dist/ui/modal/package-info-sections.js +327 -0
  30. package/dist/ui/modal/package-info.js +147 -0
  31. package/dist/ui/modal/theme-selector.js +46 -0
  32. package/dist/ui/modal/types.js +3 -0
  33. package/dist/ui/presenters/index.js +11 -0
  34. package/dist/ui/presenters/vulnerability.js +76 -0
  35. package/dist/ui/renderer/index.js +9 -11
  36. package/dist/ui/renderer/package-list.js +135 -62
  37. package/dist/ui/state/filter-manager.js +17 -2
  38. package/dist/ui/state/modal-manager.js +48 -6
  39. package/dist/ui/state/state-manager.js +42 -7
  40. package/dist/ui/utils/cursor.js +18 -0
  41. package/dist/ui/utils/index.js +8 -1
  42. package/dist/ui/utils/terminal-input.js +125 -0
  43. package/dist/ui/utils/text.js +75 -0
  44. package/dist/ui/utils/version.js +3 -2
  45. package/dist/utils/git.js +33 -0
  46. package/dist/utils/index.js +1 -0
  47. package/package.json +22 -19
  48. package/dist/services/changelog-fetcher.js +0 -215
  49. package/dist/ui/renderer/modal.js +0 -190
  50. package/dist/ui/renderer/theme-selector.js +0 -83
@@ -1,190 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.renderPackageInfoLoading = renderPackageInfoLoading;
7
- exports.renderPackageInfoModal = renderPackageInfoModal;
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const themes_colors_1 = require("../themes-colors");
10
- const utils_1 = require("../utils");
11
- // Use shared ANSI stripping utility
12
- const stripAnsi = utils_1.VersionUtils.stripAnsi;
13
- /**
14
- * Format a number for display (e.g., 1000000 -> "1M", 1000 -> "1K")
15
- */
16
- function formatNumber(num) {
17
- if (!num)
18
- return 'N/A';
19
- if (num >= 1000000)
20
- return (num / 1000000).toFixed(1) + 'M';
21
- if (num >= 1000)
22
- return (num / 1000).toFixed(1) + 'K';
23
- return num.toString();
24
- }
25
- /**
26
- * Wrap text to fit within max width
27
- */
28
- function wrapText(text, maxWidth) {
29
- if (text.length <= maxWidth) {
30
- return [text];
31
- }
32
- const lines = [];
33
- let current = '';
34
- const words = text.split(' ');
35
- for (const word of words) {
36
- if ((current + ' ' + word).length > maxWidth) {
37
- if (current)
38
- lines.push(current);
39
- current = word;
40
- }
41
- else {
42
- current = current ? current + ' ' + word : word;
43
- }
44
- }
45
- if (current)
46
- lines.push(current);
47
- return lines;
48
- }
49
- /**
50
- * Render a loading state for the info modal
51
- */
52
- function renderPackageInfoLoading(state, terminalWidth = 80, terminalHeight = 24) {
53
- const modalWidth = Math.min(terminalWidth - 6, 120);
54
- const padding = Math.floor((terminalWidth - modalWidth) / 2);
55
- const lines = [];
56
- // Top padding to center vertically
57
- const topPadding = Math.max(1, Math.floor((terminalHeight - 10) / 2));
58
- for (let i = 0; i < topPadding; i++) {
59
- lines.push('');
60
- }
61
- // Modal border
62
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╭' + '─'.repeat(modalWidth - 2) + '╮'));
63
- // Loading message
64
- const loadingMsg = '⏳ Loading package info...';
65
- const msgPadding = modalWidth - 4 - stripAnsi(loadingMsg).length;
66
- lines.push(' '.repeat(padding) +
67
- chalk_1.default.gray('│') +
68
- ' ' +
69
- chalk_1.default.cyan(loadingMsg) +
70
- ' '.repeat(Math.max(0, msgPadding)) +
71
- chalk_1.default.gray('│'));
72
- // Package name
73
- const nameMsg = `${state.name}`;
74
- const namePadding = modalWidth - 4 - nameMsg.length;
75
- lines.push(' '.repeat(padding) +
76
- chalk_1.default.gray('│') +
77
- ' ' +
78
- chalk_1.default.white(nameMsg) +
79
- ' '.repeat(Math.max(0, namePadding)) +
80
- chalk_1.default.gray('│'));
81
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╰' + '─'.repeat(modalWidth - 2) + '╯'));
82
- return lines;
83
- }
84
- /**
85
- * Render a full-screen modal overlay showing package information
86
- * Similar to Turbo's help menu - centered with disabled background
87
- */
88
- function renderPackageInfoModal(state, terminalWidth = 80, terminalHeight = 24) {
89
- const modalWidth = Math.min(terminalWidth - 6, 120); // Leave margins
90
- const padding = Math.floor((terminalWidth - modalWidth) / 2);
91
- const lines = [];
92
- // Top padding to center vertically
93
- const topPadding = Math.max(1, Math.floor((terminalHeight - 20) / 2));
94
- for (let i = 0; i < topPadding; i++) {
95
- lines.push('');
96
- }
97
- // Modal border and header
98
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╭' + '─'.repeat(modalWidth - 2) + '╮'));
99
- // Title with package name
100
- const title = ` ℹ️ ${state.name}`;
101
- const titleLength = stripAnsi(title).length;
102
- const titlePadding = Math.max(0, modalWidth - 2 - titleLength);
103
- lines.push(' '.repeat(padding) +
104
- chalk_1.default.gray('│') +
105
- chalk_1.default.cyan.bold(title) +
106
- ' '.repeat(titlePadding) +
107
- chalk_1.default.gray('│'));
108
- // License and author line
109
- const authorLicense = `${state.author || 'Unknown'} • ${state.license || 'MIT'}`;
110
- const authorLength = authorLicense.length;
111
- const authorPadding = Math.max(0, modalWidth - 3 - authorLength);
112
- lines.push(' '.repeat(padding) +
113
- chalk_1.default.gray('│') +
114
- ' ' +
115
- chalk_1.default.gray(authorLicense) +
116
- ' '.repeat(authorPadding) +
117
- chalk_1.default.gray('│'));
118
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
119
- // Current and target versions
120
- const currentVersion = chalk_1.default.yellow(state.currentVersionSpecifier);
121
- const targetVersion = chalk_1.default.green(state.selectedOption === 'range' ? state.rangeVersion : state.latestVersion);
122
- const versionText = `Current: ${currentVersion} → Target: ${targetVersion}`;
123
- const versionLength = stripAnsi(versionText).length;
124
- const versionPadding = Math.max(0, modalWidth - 3 - versionLength);
125
- lines.push(' '.repeat(padding) +
126
- chalk_1.default.gray('│') +
127
- ' ' +
128
- versionText +
129
- ' '.repeat(versionPadding) +
130
- chalk_1.default.gray('│'));
131
- // Weekly downloads
132
- if (state.weeklyDownloads !== undefined) {
133
- const downloadsText = `📊 ${formatNumber(state.weeklyDownloads)} downloads/week`;
134
- const downloadsLength = stripAnsi(downloadsText).length;
135
- const downloadsPadding = Math.max(0, modalWidth - 3 - downloadsLength);
136
- lines.push(' '.repeat(padding) +
137
- chalk_1.default.gray('│') +
138
- ' ' +
139
- (0, themes_colors_1.getThemeColor)('primary')(downloadsText) +
140
- ' '.repeat(downloadsPadding) +
141
- chalk_1.default.gray('│'));
142
- }
143
- // Description
144
- if (state.description) {
145
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
146
- const descriptionLines = wrapText(state.description, modalWidth - 4);
147
- for (const descLine of descriptionLines) {
148
- const descLength = descLine.length;
149
- const descPadding = Math.max(0, modalWidth - 3 - descLength);
150
- lines.push(' '.repeat(padding) +
151
- chalk_1.default.gray('│') +
152
- ' ' +
153
- chalk_1.default.white(descLine) +
154
- ' '.repeat(descPadding) +
155
- chalk_1.default.gray('│'));
156
- }
157
- }
158
- // Changelog/Releases section (moved to middle)
159
- if (state.repository) {
160
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
161
- const repoLabel = 'Changelog:';
162
- const repoUrl = state.repository.substring(0, modalWidth - 20);
163
- const repoText = ` ${repoLabel} ${chalk_1.default.underline((0, themes_colors_1.getThemeColor)('primary')(repoUrl))}`;
164
- const repoLength = stripAnsi(repoText).length;
165
- const repoPadding = Math.max(0, modalWidth - 3 - repoLength);
166
- lines.push(' '.repeat(padding) +
167
- chalk_1.default.gray('│') +
168
- repoText +
169
- ' '.repeat(repoPadding) +
170
- chalk_1.default.gray('│'));
171
- }
172
- // Links section
173
- if (state.homepage) {
174
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(modalWidth - 2) + '┤'));
175
- const homeLabel = 'Homepage:';
176
- const homeUrl = state.homepage.substring(0, modalWidth - 20);
177
- const homeText = ` ${homeLabel} ${chalk_1.default.underline((0, themes_colors_1.getThemeColor)('primary')(homeUrl))}`;
178
- const homeLength = stripAnsi(homeText).length;
179
- const homePadding = Math.max(0, modalWidth - 3 - homeLength);
180
- lines.push(' '.repeat(padding) +
181
- chalk_1.default.gray('│') +
182
- homeText +
183
- ' '.repeat(homePadding) +
184
- chalk_1.default.gray('│'));
185
- }
186
- // Footer
187
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╰' + '─'.repeat(modalWidth - 2) + '╯'));
188
- return lines;
189
- }
190
- //# sourceMappingURL=modal.js.map
@@ -1,83 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.renderThemeSelectorModal = renderThemeSelectorModal;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- const themes_1 = require("../themes");
9
- /**
10
- * Get the visual length of a string (ignoring ANSI color codes)
11
- * Accounts for wide characters like emojis
12
- */
13
- function getVisualLength(str) {
14
- const cleaned = str.replace(/\u001b\[[0-9;]*m/g, '');
15
- let length = 0;
16
- for (const char of cleaned) {
17
- const code = char.charCodeAt(0);
18
- // Emoji ranges: 0x1F000–0x1F9FF (and other ranges)
19
- if (code >= 0x1F000 || code >= 0x2600) {
20
- length += 2;
21
- }
22
- else {
23
- length += 1;
24
- }
25
- }
26
- return length;
27
- }
28
- /**
29
- * Render the theme selector modal
30
- */
31
- function renderThemeSelectorModal(currentTheme, previewTheme, terminalWidth = 80, terminalHeight = 24) {
32
- const maxModalWidth = 76; // Fixed width that fits comfortably in 80-char terminal
33
- const padding = Math.max(0, Math.floor((terminalWidth - maxModalWidth) / 2));
34
- const lines = [];
35
- const contentWidth = maxModalWidth - 4; // Account for '│ ' on left and ' │' on right
36
- // Helper to pad content to exact width
37
- const createLine = (content) => {
38
- const visualLen = getVisualLength(content);
39
- const spacesNeeded = Math.max(0, contentWidth - visualLen);
40
- const line = ' '.repeat(padding) + chalk_1.default.gray('│') + ' ' + content + ' '.repeat(spacesNeeded) + ' ' + chalk_1.default.gray('│');
41
- return line;
42
- };
43
- // Top padding to center vertically
44
- const topPadding = Math.max(1, Math.floor((terminalHeight - themes_1.themeNames.length - 8) / 2));
45
- for (let i = 0; i < topPadding; i++) {
46
- lines.push('');
47
- }
48
- // Top border
49
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╭' + '─'.repeat(maxModalWidth - 2) + '╮'));
50
- // Title
51
- const title = chalk_1.default.cyan('🎨 Select Theme');
52
- lines.push(createLine(title));
53
- // Separator
54
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(maxModalWidth - 2) + '┤'));
55
- // Theme options
56
- for (const themeName of themes_1.themeNames) {
57
- const isSelected = themeName === previewTheme;
58
- const isCurrent = themeName === currentTheme;
59
- const themeObj = themes_1.themes[themeName];
60
- // Build the theme line
61
- let themeLine = '';
62
- if (isSelected) {
63
- themeLine = chalk_1.default.green('● ');
64
- }
65
- else {
66
- themeLine = chalk_1.default.gray('○ ');
67
- }
68
- themeLine += themeObj.name;
69
- if (isCurrent) {
70
- themeLine += chalk_1.default.gray(' (current)');
71
- }
72
- lines.push(createLine(themeLine));
73
- }
74
- // Separator before instructions
75
- lines.push(' '.repeat(padding) + chalk_1.default.gray('├' + '─'.repeat(maxModalWidth - 2) + '┤'));
76
- // Instructions
77
- const instruction = chalk_1.default.gray('↑/↓ to navigate • Enter to confirm • Esc to cancel');
78
- lines.push(createLine(instruction));
79
- // Bottom border
80
- lines.push(' '.repeat(padding) + chalk_1.default.gray('╰' + '─'.repeat(maxModalWidth - 2) + '╯'));
81
- return lines;
82
- }
83
- //# sourceMappingURL=theme-selector.js.map