inup 1.4.0

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.
@@ -0,0 +1,172 @@
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.PackageManagerDetector = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const PACKAGE_MANAGERS = {
11
+ npm: {
12
+ name: 'npm',
13
+ displayName: 'npm',
14
+ lockFile: 'package-lock.json',
15
+ workspaceFile: null, // Uses package.json workspaces field
16
+ installCommand: 'npm install',
17
+ color: chalk_1.default.red,
18
+ },
19
+ yarn: {
20
+ name: 'yarn',
21
+ displayName: 'yarn',
22
+ lockFile: 'yarn.lock',
23
+ workspaceFile: null, // Uses package.json workspaces field
24
+ installCommand: 'yarn install',
25
+ color: chalk_1.default.blue,
26
+ },
27
+ pnpm: {
28
+ name: 'pnpm',
29
+ displayName: 'pnpm',
30
+ lockFile: 'pnpm-lock.yaml',
31
+ workspaceFile: 'pnpm-workspace.yaml',
32
+ installCommand: 'pnpm install',
33
+ color: chalk_1.default.yellow,
34
+ },
35
+ bun: {
36
+ name: 'bun',
37
+ displayName: 'bun',
38
+ lockFile: 'bun.lockb',
39
+ workspaceFile: null, // Uses package.json workspaces field
40
+ installCommand: 'bun install',
41
+ color: chalk_1.default.magenta,
42
+ },
43
+ };
44
+ class PackageManagerDetector {
45
+ /**
46
+ * Detect package manager from packageManager field or lock files
47
+ */
48
+ static detect(cwd = process.cwd()) {
49
+ // 1. Check packageManager field in package.json
50
+ const fromPackageJson = this.detectFromPackageJson(cwd);
51
+ if (fromPackageJson) {
52
+ return fromPackageJson;
53
+ }
54
+ // 2. Check for lock files
55
+ const fromLockFile = this.detectFromLockFiles(cwd);
56
+ if (fromLockFile) {
57
+ return fromLockFile;
58
+ }
59
+ // 3. Fallback to npm
60
+ console.log(chalk_1.default.yellow('⚠️ No package manager detected. Defaulting to npm. Consider adding a "packageManager" field to your package.json.'));
61
+ return PACKAGE_MANAGERS.npm;
62
+ }
63
+ /**
64
+ * Detect from package.json packageManager field
65
+ */
66
+ static detectFromPackageJson(cwd) {
67
+ const packageJsonPath = (0, path_1.join)(cwd, 'package.json');
68
+ if (!(0, fs_1.existsSync)(packageJsonPath)) {
69
+ return null;
70
+ }
71
+ try {
72
+ const content = (0, fs_1.readFileSync)(packageJsonPath, 'utf-8');
73
+ const packageJson = JSON.parse(content);
74
+ if (packageJson.packageManager) {
75
+ // Parse format: "pnpm@10.28.1" or "npm@9.0.0+sha512.abc..."
76
+ const match = packageJson.packageManager.match(/^(npm|yarn|pnpm|bun)(@|$)/);
77
+ if (match) {
78
+ const pmName = match[1];
79
+ return PACKAGE_MANAGERS[pmName];
80
+ }
81
+ }
82
+ }
83
+ catch (error) {
84
+ // Invalid package.json, continue to lock file detection
85
+ }
86
+ return null;
87
+ }
88
+ /**
89
+ * Detect from lock files (with priority and recency)
90
+ */
91
+ static detectFromLockFiles(cwd) {
92
+ const lockFileChecks = [
93
+ { pm: PACKAGE_MANAGERS.pnpm, path: (0, path_1.join)(cwd, 'pnpm-lock.yaml') },
94
+ { pm: PACKAGE_MANAGERS.bun, path: (0, path_1.join)(cwd, 'bun.lockb') },
95
+ { pm: PACKAGE_MANAGERS.yarn, path: (0, path_1.join)(cwd, 'yarn.lock') },
96
+ { pm: PACKAGE_MANAGERS.npm, path: (0, path_1.join)(cwd, 'package-lock.json') },
97
+ ];
98
+ const existingLocks = lockFileChecks
99
+ .filter(({ path }) => (0, fs_1.existsSync)(path))
100
+ .map(({ pm, path }) => ({
101
+ pm,
102
+ path,
103
+ mtime: (0, fs_1.statSync)(path).mtime.getTime(),
104
+ }));
105
+ if (existingLocks.length === 0) {
106
+ return null;
107
+ }
108
+ // If multiple lock files, use most recently modified
109
+ if (existingLocks.length > 1) {
110
+ console.log(chalk_1.default.yellow('⚠️ Multiple lock files detected. Using most recently modified. Consider cleaning up unused lock files.'));
111
+ existingLocks.sort((a, b) => b.mtime - a.mtime);
112
+ }
113
+ return existingLocks[0].pm;
114
+ }
115
+ /**
116
+ * Get package manager info by name
117
+ */
118
+ static getInfo(name) {
119
+ return PACKAGE_MANAGERS[name];
120
+ }
121
+ /**
122
+ * Find workspace root for any package manager
123
+ */
124
+ static findWorkspaceRoot(cwd = process.cwd(), packageManager) {
125
+ const pmInfo = PACKAGE_MANAGERS[packageManager];
126
+ let currentDir = cwd;
127
+ while (currentDir !== (0, path_1.join)(currentDir, '..')) {
128
+ // Check for package manager-specific workspace file
129
+ if (pmInfo.workspaceFile) {
130
+ const workspaceFilePath = (0, path_1.join)(currentDir, pmInfo.workspaceFile);
131
+ if ((0, fs_1.existsSync)(workspaceFilePath)) {
132
+ return currentDir;
133
+ }
134
+ }
135
+ else {
136
+ // Check for package.json with workspaces field
137
+ const packageJsonPath = (0, path_1.join)(currentDir, 'package.json');
138
+ if ((0, fs_1.existsSync)(packageJsonPath)) {
139
+ try {
140
+ const content = (0, fs_1.readFileSync)(packageJsonPath, 'utf-8');
141
+ const packageJson = JSON.parse(content);
142
+ // Check if workspaces field exists and is non-empty
143
+ if (packageJson.workspaces) {
144
+ if (Array.isArray(packageJson.workspaces) && packageJson.workspaces.length > 0) {
145
+ return currentDir;
146
+ }
147
+ else if (typeof packageJson.workspaces === 'object' &&
148
+ packageJson.workspaces.packages &&
149
+ packageJson.workspaces.packages.length > 0) {
150
+ // Yarn berry format: { packages: [...] }
151
+ return currentDir;
152
+ }
153
+ }
154
+ }
155
+ catch (error) {
156
+ // Invalid package.json, continue searching
157
+ }
158
+ }
159
+ }
160
+ currentDir = (0, path_1.join)(currentDir, '..');
161
+ }
162
+ return null;
163
+ }
164
+ /**
165
+ * Check if directory is in a workspace
166
+ */
167
+ static isInWorkspace(cwd, packageManager) {
168
+ return this.findWorkspaceRoot(cwd, packageManager) !== null;
169
+ }
170
+ }
171
+ exports.PackageManagerDetector = PackageManagerDetector;
172
+ //# sourceMappingURL=package-manager-detector.js.map
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.checkForUpdate = checkForUpdate;
37
+ exports.checkForUpdateAsync = checkForUpdateAsync;
38
+ const child_process_1 = require("child_process");
39
+ const semver = __importStar(require("semver"));
40
+ const constants_1 = require("../constants");
41
+ /**
42
+ * Check if the current package version is outdated compared to npm registry
43
+ */
44
+ async function checkForUpdate(packageName, currentVersion) {
45
+ try {
46
+ // Use npm view to get the latest version from registry
47
+ const result = (0, child_process_1.execSync)(`npm view ${packageName} version`, {
48
+ encoding: 'utf-8',
49
+ timeout: constants_1.REQUEST_TIMEOUT,
50
+ stdio: ['pipe', 'pipe', 'pipe'],
51
+ });
52
+ const latestVersion = result.trim();
53
+ // Compare versions
54
+ const isOutdated = semver.lt(currentVersion, latestVersion);
55
+ // Determine update command based on how the tool was likely invoked
56
+ // Check if we're running via npx (node_modules/.bin path indicates local/npx)
57
+ const isNpx = process.argv[1]?.includes('.npm') || process.argv[1]?.includes('_npx');
58
+ const updateCommand = isNpx ? `npx inup@latest` : `npm install -g inup@latest`;
59
+ return {
60
+ currentVersion,
61
+ latestVersion,
62
+ isOutdated,
63
+ updateCommand,
64
+ };
65
+ }
66
+ catch (error) {
67
+ // Silently fail - don't interrupt the user experience
68
+ return null;
69
+ }
70
+ }
71
+ /**
72
+ * Check for updates in the background without blocking
73
+ * Resolves immediately, result available via promise
74
+ */
75
+ function checkForUpdateAsync(packageName, currentVersion) {
76
+ return new Promise((resolve) => {
77
+ // Set a timeout to prevent hanging
78
+ const timeout = setTimeout(() => {
79
+ resolve(null);
80
+ }, 5000);
81
+ checkForUpdate(packageName, currentVersion)
82
+ .then((result) => {
83
+ clearTimeout(timeout);
84
+ resolve(result);
85
+ })
86
+ .catch(() => {
87
+ clearTimeout(timeout);
88
+ resolve(null);
89
+ });
90
+ });
91
+ }
92
+ //# sourceMappingURL=version-checker.js.map
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmationInputHandler = exports.InputHandler = exports.UIRenderer = exports.StateManager = exports.VersionUtils = void 0;
4
+ var utils_1 = require("./utils");
5
+ Object.defineProperty(exports, "VersionUtils", { enumerable: true, get: function () { return utils_1.VersionUtils; } });
6
+ var state_1 = require("./state");
7
+ Object.defineProperty(exports, "StateManager", { enumerable: true, get: function () { return state_1.StateManager; } });
8
+ var index_1 = require("./renderer/index");
9
+ Object.defineProperty(exports, "UIRenderer", { enumerable: true, get: function () { return index_1.UIRenderer; } });
10
+ var input_handler_1 = require("./input-handler");
11
+ Object.defineProperty(exports, "InputHandler", { enumerable: true, get: function () { return input_handler_1.InputHandler; } });
12
+ Object.defineProperty(exports, "ConfirmationInputHandler", { enumerable: true, get: function () { return input_handler_1.ConfirmationInputHandler; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfirmationInputHandler = exports.InputHandler = void 0;
4
+ class InputHandler {
5
+ constructor(stateManager, onAction, onConfirm, onCancel) {
6
+ this.stateManager = stateManager;
7
+ this.onAction = onAction;
8
+ this.onConfirm = onConfirm;
9
+ this.onCancel = onCancel;
10
+ }
11
+ handleKeypress(str, key, states) {
12
+ if (key.ctrl && key.name === 'c') {
13
+ process.exit(0);
14
+ }
15
+ switch (key.name) {
16
+ case 'up':
17
+ this.onAction({ type: 'navigate_up' });
18
+ break;
19
+ case 'down':
20
+ this.onAction({ type: 'navigate_down' });
21
+ break;
22
+ case 'left':
23
+ this.onAction({ type: 'select_left' });
24
+ break;
25
+ case 'right':
26
+ this.onAction({ type: 'select_right' });
27
+ break;
28
+ case 'return':
29
+ // Check if any packages are selected
30
+ const selectedCount = states.filter((s) => s.selectedOption !== 'none').length;
31
+ if (selectedCount === 0) {
32
+ // Show warning and stay in selection mode
33
+ console.log('\n' +
34
+ '\x1b[33m⚠️ No packages selected. Press ↑/↓ to navigate and ←/→ to select versions, or ESC to exit.\x1b[39m');
35
+ // Re-render will happen automatically
36
+ return;
37
+ }
38
+ this.cleanup();
39
+ this.onConfirm(states);
40
+ return;
41
+ case 'm':
42
+ case 'M':
43
+ this.onAction({ type: 'bulk_select_minor' });
44
+ break;
45
+ case 'l':
46
+ case 'L':
47
+ this.onAction({ type: 'bulk_select_latest' });
48
+ break;
49
+ case 'u':
50
+ case 'U':
51
+ this.onAction({ type: 'bulk_unselect_all' });
52
+ break;
53
+ case 'i':
54
+ case 'I':
55
+ this.onAction({ type: 'toggle_info_modal' });
56
+ break;
57
+ case 'escape':
58
+ // Check if modal is open - if so, close it; otherwise cancel
59
+ const uiState = this.stateManager.getUIState();
60
+ if (uiState.showInfoModal) {
61
+ this.onAction({ type: 'toggle_info_modal' });
62
+ }
63
+ else {
64
+ this.onAction({ type: 'cancel' });
65
+ }
66
+ break;
67
+ }
68
+ }
69
+ handleResize(height) {
70
+ this.onAction({ type: 'resize', height });
71
+ }
72
+ cleanup() {
73
+ if (process.stdin.setRawMode) {
74
+ process.stdin.setRawMode(false);
75
+ }
76
+ process.stdin.pause();
77
+ }
78
+ }
79
+ exports.InputHandler = InputHandler;
80
+ class ConfirmationInputHandler {
81
+ constructor(onConfirm) {
82
+ this.onConfirm = onConfirm;
83
+ }
84
+ handleKeypress(str, key) {
85
+ if (key.ctrl && key.name === 'c') {
86
+ process.exit(0);
87
+ }
88
+ switch (key.name) {
89
+ case 'y':
90
+ case 'return':
91
+ this.cleanup();
92
+ this.onConfirm(true);
93
+ break;
94
+ case 'n':
95
+ this.cleanup();
96
+ this.onConfirm(null); // Go back to selection
97
+ break;
98
+ case 'escape':
99
+ this.cleanup();
100
+ this.onConfirm(false); // Cancel
101
+ break;
102
+ }
103
+ }
104
+ cleanup() {
105
+ if (process.stdin.setRawMode) {
106
+ process.stdin.setRawMode(false);
107
+ }
108
+ process.stdin.pause();
109
+ }
110
+ }
111
+ exports.ConfirmationInputHandler = ConfirmationInputHandler;
112
+ //# sourceMappingURL=input-handler.js.map
@@ -0,0 +1,34 @@
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.renderConfirmation = renderConfirmation;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ /**
9
+ * Render confirmation screen
10
+ */
11
+ function renderConfirmation(choices) {
12
+ if (choices.length === 0) {
13
+ return chalk_1.default.yellow('No packages selected for upgrade.');
14
+ }
15
+ // Group choices by package name to show unique packages
16
+ const packagesByName = new Map();
17
+ choices.forEach((choice) => {
18
+ if (!packagesByName.has(choice.name)) {
19
+ packagesByName.set(choice.name, []);
20
+ }
21
+ packagesByName.get(choice.name).push(choice);
22
+ });
23
+ let output = chalk_1.default.bold(`\n🚀 Ready to upgrade ${packagesByName.size} package(s):\n`);
24
+ packagesByName.forEach((packageChoices, packageName) => {
25
+ // Use the first choice for display (they should all have the same target version for the same package)
26
+ const choice = packageChoices[0];
27
+ const upgradeTypeColor = choice.upgradeType === 'range' ? chalk_1.default.yellow : chalk_1.default.red;
28
+ const instancesText = packageChoices.length > 1 ? chalk_1.default.gray(` (${packageChoices.length} instances)`) : '';
29
+ output += ` • ${chalk_1.default.cyan(packageName)} → ${upgradeTypeColor(choice.targetVersion)} ${chalk_1.default.gray(`(${choice.upgradeType})`)}${instancesText}\n`;
30
+ });
31
+ output += chalk_1.default.gray('Press Enter/Y to proceed, N to go back to selection, ESC to cancel\n');
32
+ return output;
33
+ }
34
+ //# sourceMappingURL=confirmation.js.map
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.UIRenderer = void 0;
40
+ const PackageList = __importStar(require("./package-list"));
41
+ const Confirmation = __importStar(require("./confirmation"));
42
+ const Modal = __importStar(require("./modal"));
43
+ /**
44
+ * Main UI renderer class that composes all rendering parts
45
+ */
46
+ class UIRenderer {
47
+ renderPackageLine(state, index, isCurrentRow) {
48
+ return PackageList.renderPackageLine(state, index, isCurrentRow);
49
+ }
50
+ renderSectionHeader(title, sectionType) {
51
+ return PackageList.renderSectionHeader(title, sectionType);
52
+ }
53
+ renderSpacer() {
54
+ return PackageList.renderSpacer();
55
+ }
56
+ renderInterface(states, currentRow, scrollOffset, maxVisibleItems, isInitialRender, renderableItems, dependencyTypeLabel, packageManager) {
57
+ return PackageList.renderInterface(states, currentRow, scrollOffset, maxVisibleItems, isInitialRender, renderableItems, dependencyTypeLabel, packageManager);
58
+ }
59
+ renderPackagesTable(packages) {
60
+ return PackageList.renderPackagesTable(packages);
61
+ }
62
+ renderConfirmation(choices) {
63
+ return Confirmation.renderConfirmation(choices);
64
+ }
65
+ renderPackageInfoLoading(state, terminalWidth = 80, terminalHeight = 24) {
66
+ return Modal.renderPackageInfoLoading(state, terminalWidth, terminalHeight);
67
+ }
68
+ renderPackageInfoModal(state, terminalWidth = 80, terminalHeight = 24) {
69
+ return Modal.renderPackageInfoModal(state, terminalWidth, terminalHeight);
70
+ }
71
+ }
72
+ exports.UIRenderer = UIRenderer;
73
+ // Re-export all functions for direct use if needed
74
+ __exportStar(require("./package-list"), exports);
75
+ __exportStar(require("./confirmation"), exports);
76
+ __exportStar(require("./modal"), exports);
77
+ //# sourceMappingURL=index.js.map