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.
- package/LICENSE +21 -0
- package/README.md +39 -30
- package/dist/cli.js +29 -14
- package/dist/config/project-config.js +6 -0
- package/dist/core/package-detector.js +3 -2
- package/dist/core/upgrade-runner.js +6 -3
- package/dist/features/changelog/clients/github-client.js +134 -0
- package/dist/features/changelog/clients/npm-registry-client.js +53 -0
- package/dist/features/changelog/index.js +19 -0
- package/dist/features/changelog/parsers/changelog-parser.js +68 -0
- package/dist/features/changelog/parsers/github-release-html-parser.js +61 -0
- package/dist/features/changelog/parsers/package-metadata.js +34 -0
- package/dist/features/changelog/parsers/repository-ref.js +26 -0
- package/dist/features/changelog/services/changelog-service.js +30 -0
- package/dist/features/changelog/services/package-metadata-service.js +108 -0
- package/dist/features/changelog/services/release-notes-service.js +180 -0
- package/dist/features/changelog/types/changelog.types.js +3 -0
- package/dist/interactive-ui.js +242 -114
- package/dist/services/background-audit.js +60 -0
- package/dist/services/index.js +3 -1
- package/dist/services/vulnerability-checker.js +133 -0
- package/dist/ui/controllers/index.js +8 -0
- package/dist/ui/controllers/package-info-modal-controller.js +237 -0
- package/dist/ui/controllers/vulnerability-audit-controller.js +82 -0
- package/dist/ui/index.js +3 -0
- package/dist/ui/input-handler.js +40 -9
- package/dist/ui/modal/index.js +22 -0
- package/dist/ui/modal/layout.js +84 -0
- package/dist/ui/modal/package-info-sections.js +327 -0
- package/dist/ui/modal/package-info.js +147 -0
- package/dist/ui/modal/theme-selector.js +46 -0
- package/dist/ui/modal/types.js +3 -0
- package/dist/ui/presenters/index.js +11 -0
- package/dist/ui/presenters/vulnerability.js +76 -0
- package/dist/ui/renderer/index.js +9 -11
- package/dist/ui/renderer/package-list.js +135 -62
- package/dist/ui/state/filter-manager.js +17 -2
- package/dist/ui/state/modal-manager.js +48 -6
- package/dist/ui/state/state-manager.js +42 -7
- package/dist/ui/utils/cursor.js +18 -0
- package/dist/ui/utils/index.js +8 -1
- package/dist/ui/utils/terminal-input.js +125 -0
- package/dist/ui/utils/text.js +75 -0
- package/dist/ui/utils/version.js +3 -2
- package/dist/utils/git.js +33 -0
- package/dist/utils/index.js +1 -0
- package/package.json +22 -19
- package/dist/services/changelog-fetcher.js +0 -215
- package/dist/ui/renderer/modal.js +0 -190
- 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
|