inup 1.6.7 → 1.6.8
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/README.md +9 -2
- package/dist/app/interactive-ui.js +17 -15
- package/dist/app/upgrade-runner.js +11 -16
- package/dist/cli.js +12 -13
- package/dist/features/audit/headless-audit.js +4 -11
- package/dist/features/audit/index.js +9 -9
- package/dist/features/audit/presenter.js +0 -2
- package/dist/features/audit/vulnerability-audit-controller.js +3 -3
- package/dist/features/audit/vulnerability-checker.js +1 -5
- package/dist/features/changelog/clients/github-client.js +9 -7
- package/dist/features/changelog/index.js +1 -1
- package/dist/features/changelog/services/package-metadata-service.js +1 -1
- package/dist/features/changelog/services/release-notes-service.js +3 -2
- package/dist/features/debug/index.js +2 -2
- package/dist/features/debug/perf-logger.js +14 -14
- package/dist/features/headless/headless-runner.js +22 -9
- package/dist/features/headless/index.js +1 -1
- package/dist/features/interactive/index.js +10 -10
- package/dist/features/interactive/input-handler.js +3 -3
- package/dist/features/interactive/modal/index.js +1 -1
- package/dist/features/interactive/modal/layout.js +3 -3
- package/dist/features/interactive/modal/package-info-sections/index.js +1 -1
- package/dist/features/interactive/modal/package-info-sections/release-notes.js +1 -1
- package/dist/features/interactive/modal/package-info-sections/sections.js +5 -5
- package/dist/features/interactive/modal/package-info-sections/text.js +1 -1
- package/dist/features/interactive/modal/package-info.js +15 -18
- package/dist/features/interactive/renderer/confirmation.js +6 -3
- package/dist/features/interactive/renderer/help-modal.js +3 -3
- package/dist/features/interactive/renderer/index.js +3 -3
- package/dist/features/interactive/renderer/package-list/index.js +1 -1
- package/dist/features/interactive/renderer/package-list/interface.js +9 -9
- package/dist/features/interactive/renderer/package-list/rows.js +8 -9
- package/dist/features/interactive/renderer/performance-modal.js +2 -2
- package/dist/features/interactive/renderer/version-format.js +4 -4
- package/dist/features/interactive/session/action-dispatcher.js +2 -2
- package/dist/features/interactive/session/index.js +4 -4
- package/dist/features/interactive/session/interactive-session.js +9 -8
- package/dist/features/interactive/session/selection-state-builder.js +5 -4
- package/dist/features/interactive/state/filter-manager.js +1 -1
- package/dist/features/interactive/state/index.js +7 -7
- package/dist/features/interactive/state/state-manager.js +4 -4
- package/dist/features/interactive/state/theme-manager.js +4 -6
- package/dist/features/interactive/themes-colors.js +4 -5
- package/dist/features/upgrade/package-detector.js +30 -12
- package/dist/features/upgrade/upgrader.js +28 -37
- package/dist/shared/config/project-config.js +10 -11
- package/dist/shared/config/user-config.js +8 -8
- package/dist/shared/debug-logger.js +9 -9
- package/dist/shared/exec.js +4 -4
- package/dist/shared/fs/index.js +1 -1
- package/dist/shared/fs/io.js +3 -4
- package/dist/shared/fs/paths.js +4 -4
- package/dist/shared/fs/scan.js +21 -21
- package/dist/shared/git.js +3 -3
- package/dist/shared/http/resizable-semaphore.js +3 -1
- package/dist/shared/local-env.js +7 -7
- package/dist/shared/package-manager.js +25 -24
- package/dist/shared/registry/npm-registry.js +12 -10
- package/dist/shared/registry/version-checker.js +1 -1
- package/dist/shared/terminal/cursor.js +1 -1
- package/dist/shared/terminal/index.js +5 -5
- package/dist/shared/terminal/terminal-input.js +6 -2
- package/dist/shared/terminal/text.js +1 -1
- package/dist/shared/types/index.js +1 -1
- package/dist/shared/versions.js +37 -33
- package/package.json +10 -6
package/dist/shared/fs/scan.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.findAllPackageJsonFiles = findAllPackageJsonFiles;
|
|
4
4
|
exports.findAllPackageJsonFilesAsync = findAllPackageJsonFilesAsync;
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const path_1 = require("path");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
8
7
|
/**
|
|
9
8
|
* Normalize a relative path to forward slashes before matching `.inuprc` exclude patterns.
|
|
10
9
|
* On Windows `path.relative` yields backslash separators (e.g. `packages\skipme`), but users write
|
|
@@ -55,12 +54,12 @@ function classifyDirectory(name, skipSet) {
|
|
|
55
54
|
* layout). Stays shallow (depth 1) so detecting a skip doesn't re-walk the subtree we just pruned.
|
|
56
55
|
*/
|
|
57
56
|
function prunedDirHoldsPackage(dir) {
|
|
58
|
-
if ((0,
|
|
57
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'package.json'))) {
|
|
59
58
|
return true;
|
|
60
59
|
}
|
|
61
60
|
let entries;
|
|
62
61
|
try {
|
|
63
|
-
entries = (0,
|
|
62
|
+
entries = (0, node_fs_1.readdirSync)(dir);
|
|
64
63
|
}
|
|
65
64
|
catch {
|
|
66
65
|
return false;
|
|
@@ -68,9 +67,9 @@ function prunedDirHoldsPackage(dir) {
|
|
|
68
67
|
for (const entry of entries) {
|
|
69
68
|
if (entry.startsWith('.'))
|
|
70
69
|
continue;
|
|
71
|
-
const child = (0,
|
|
70
|
+
const child = (0, node_path_1.join)(dir, entry);
|
|
72
71
|
try {
|
|
73
|
-
if ((0,
|
|
72
|
+
if ((0, node_fs_1.statSync)(child).isDirectory() && (0, node_fs_1.existsSync)((0, node_path_1.join)(child, 'package.json'))) {
|
|
74
73
|
return true;
|
|
75
74
|
}
|
|
76
75
|
}
|
|
@@ -117,7 +116,7 @@ function findAllPackageJsonFiles(rootDir = process.cwd(), excludePatterns = [],
|
|
|
117
116
|
return;
|
|
118
117
|
}
|
|
119
118
|
lastProgressAt = now;
|
|
120
|
-
const relativePath = (0,
|
|
119
|
+
const relativePath = (0, node_path_1.relative)(rootDir, currentDir) || '.';
|
|
121
120
|
onProgress(relativePath, packageJsonFiles.length);
|
|
122
121
|
}
|
|
123
122
|
function traverseDirectory(dir, depth = 0) {
|
|
@@ -126,7 +125,7 @@ function findAllPackageJsonFiles(rootDir = process.cwd(), excludePatterns = [],
|
|
|
126
125
|
}
|
|
127
126
|
try {
|
|
128
127
|
// Prevent symlink cycles by tracking visited real paths
|
|
129
|
-
const realPath = (0,
|
|
128
|
+
const realPath = (0, node_fs_1.realpathSync)(dir);
|
|
130
129
|
if (visitedPaths.has(realPath)) {
|
|
131
130
|
return;
|
|
132
131
|
}
|
|
@@ -136,17 +135,17 @@ function findAllPackageJsonFiles(rootDir = process.cwd(), excludePatterns = [],
|
|
|
136
135
|
if (onProgress && (directoriesScanned % 10 === 0 || directoriesScanned === 1)) {
|
|
137
136
|
reportProgress(dir, true);
|
|
138
137
|
}
|
|
139
|
-
const files = (0,
|
|
138
|
+
const files = (0, node_fs_1.readdirSync)(dir);
|
|
140
139
|
for (const file of files) {
|
|
141
140
|
reportProgress(dir);
|
|
142
|
-
const fullPath = (0,
|
|
143
|
-
const relativePath = (0,
|
|
141
|
+
const fullPath = (0, node_path_1.join)(dir, file);
|
|
142
|
+
const relativePath = (0, node_path_1.relative)(rootDir, fullPath);
|
|
144
143
|
if (shouldExcludePath(relativePath)) {
|
|
145
144
|
continue;
|
|
146
145
|
}
|
|
147
146
|
let stat;
|
|
148
147
|
try {
|
|
149
|
-
stat = (0,
|
|
148
|
+
stat = (0, node_fs_1.statSync)(fullPath);
|
|
150
149
|
}
|
|
151
150
|
catch {
|
|
152
151
|
// Skip files/dirs we can't stat (broken symlinks, permission issues)
|
|
@@ -190,7 +189,7 @@ async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatt
|
|
|
190
189
|
return;
|
|
191
190
|
}
|
|
192
191
|
lastProgressAt = now;
|
|
193
|
-
const relativePath = (0,
|
|
192
|
+
const relativePath = (0, node_path_1.relative)(rootDir, currentDir) || '.';
|
|
194
193
|
onProgress(relativePath, packageJsonFiles.length);
|
|
195
194
|
}
|
|
196
195
|
const pending = [];
|
|
@@ -217,7 +216,7 @@ async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatt
|
|
|
217
216
|
}
|
|
218
217
|
let realPath;
|
|
219
218
|
try {
|
|
220
|
-
realPath = await
|
|
219
|
+
realPath = await node_fs_1.promises.realpath(dir);
|
|
221
220
|
}
|
|
222
221
|
catch {
|
|
223
222
|
return;
|
|
@@ -232,21 +231,21 @@ async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatt
|
|
|
232
231
|
}
|
|
233
232
|
let files;
|
|
234
233
|
try {
|
|
235
|
-
files = await
|
|
234
|
+
files = await node_fs_1.promises.readdir(dir);
|
|
236
235
|
}
|
|
237
236
|
catch {
|
|
238
237
|
return;
|
|
239
238
|
}
|
|
240
239
|
for (const file of files) {
|
|
241
240
|
reportProgress(dir);
|
|
242
|
-
const fullPath = (0,
|
|
243
|
-
const relativePath = (0,
|
|
241
|
+
const fullPath = (0, node_path_1.join)(dir, file);
|
|
242
|
+
const relativePath = (0, node_path_1.relative)(rootDir, fullPath);
|
|
244
243
|
if (shouldExcludePath(relativePath)) {
|
|
245
244
|
continue;
|
|
246
245
|
}
|
|
247
246
|
let stat;
|
|
248
247
|
try {
|
|
249
|
-
stat = await
|
|
248
|
+
stat = await node_fs_1.promises.stat(fullPath);
|
|
250
249
|
}
|
|
251
250
|
catch {
|
|
252
251
|
continue;
|
|
@@ -262,9 +261,10 @@ async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatt
|
|
|
262
261
|
}
|
|
263
262
|
}
|
|
264
263
|
function pump() {
|
|
265
|
-
while (activeTasks < concurrency &&
|
|
266
|
-
// Non-null: pending.length > 0 was just checked and nothing runs in between.
|
|
264
|
+
while (activeTasks < concurrency && !failedError) {
|
|
267
265
|
const next = pending.shift();
|
|
266
|
+
if (!next)
|
|
267
|
+
break;
|
|
268
268
|
activeTasks++;
|
|
269
269
|
void processDirectory(next.dir, next.depth)
|
|
270
270
|
.catch((error) => {
|
package/dist/shared/git.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getGitWorkingTreeState = getGitWorkingTreeState;
|
|
4
|
-
const
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
5
|
/**
|
|
6
6
|
* Detect whether cwd is a git work tree and whether it has local changes.
|
|
7
7
|
* Fail soft if git is unavailable or cwd is not a repository.
|
|
8
8
|
*/
|
|
9
9
|
function getGitWorkingTreeState(cwd) {
|
|
10
10
|
try {
|
|
11
|
-
const isInsideWorkTree = (0,
|
|
11
|
+
const isInsideWorkTree = (0, node_child_process_1.execSync)('git rev-parse --is-inside-work-tree', {
|
|
12
12
|
cwd,
|
|
13
13
|
encoding: 'utf-8',
|
|
14
14
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -16,7 +16,7 @@ function getGitWorkingTreeState(cwd) {
|
|
|
16
16
|
if (isInsideWorkTree !== 'true') {
|
|
17
17
|
return { isRepo: false, isDirty: false };
|
|
18
18
|
}
|
|
19
|
-
const status = (0,
|
|
19
|
+
const status = (0, node_child_process_1.execSync)('git status --porcelain', {
|
|
20
20
|
cwd,
|
|
21
21
|
encoding: 'utf-8',
|
|
22
22
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -60,8 +60,10 @@ class ResizableSemaphore {
|
|
|
60
60
|
* each as it is admitted so the count stays authoritative and synchronous.
|
|
61
61
|
*/
|
|
62
62
|
drainWaiters() {
|
|
63
|
-
while (this.inFlight < this.limit
|
|
63
|
+
while (this.inFlight < this.limit) {
|
|
64
64
|
const next = this.waiters.shift();
|
|
65
|
+
if (!next)
|
|
66
|
+
break;
|
|
65
67
|
this.inFlight++;
|
|
66
68
|
next();
|
|
67
69
|
}
|
package/dist/shared/local-env.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadInupLocalEnv = loadInupLocalEnv;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
6
|
/**
|
|
7
7
|
* Loads a gitignored `.env.local` from the inup repo itself (NOT the cwd), so
|
|
8
8
|
* developer-only toggles can be "set once" and apply to every `inup` run in any
|
|
@@ -21,15 +21,15 @@ const ENV_FILE_NAME = '.env.local';
|
|
|
21
21
|
/** Walk upward from this file's dir to find the .env.local; null if none. */
|
|
22
22
|
function findEnvFile() {
|
|
23
23
|
let dir = __dirname;
|
|
24
|
-
const root = (0,
|
|
24
|
+
const root = (0, node_path_1.parse)(dir).root;
|
|
25
25
|
// Cap the walk so a missing file can never loop unbounded.
|
|
26
26
|
for (let i = 0; i < 12; i++) {
|
|
27
|
-
const candidate = (0,
|
|
28
|
-
if ((0,
|
|
27
|
+
const candidate = (0, node_path_1.join)(dir, ENV_FILE_NAME);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(candidate))
|
|
29
29
|
return candidate;
|
|
30
30
|
if (dir === root)
|
|
31
31
|
break;
|
|
32
|
-
dir = (0,
|
|
32
|
+
dir = (0, node_path_1.dirname)(dir);
|
|
33
33
|
}
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
@@ -65,7 +65,7 @@ function loadInupLocalEnv() {
|
|
|
65
65
|
const file = findEnvFile();
|
|
66
66
|
if (!file)
|
|
67
67
|
return null;
|
|
68
|
-
const parsed = parseEnv((0,
|
|
68
|
+
const parsed = parseEnv((0, node_fs_1.readFileSync)(file, 'utf8'));
|
|
69
69
|
for (const [key, value] of Object.entries(parsed)) {
|
|
70
70
|
if (process.env[key] === undefined) {
|
|
71
71
|
process.env[key] = value;
|
|
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.PackageManagerDetector = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const PACKAGE_MANAGERS = {
|
|
11
11
|
npm: {
|
|
@@ -45,18 +45,19 @@ const PACKAGE_MANAGERS = {
|
|
|
45
45
|
color: chalk_1.default.magenta,
|
|
46
46
|
},
|
|
47
47
|
};
|
|
48
|
+
// biome-ignore lint/complexity/noStaticOnlyClass: intentional namespace-style API used throughout the codebase
|
|
48
49
|
class PackageManagerDetector {
|
|
49
50
|
/**
|
|
50
51
|
* Detect package manager from packageManager field or lock files
|
|
51
52
|
*/
|
|
52
53
|
static detect(cwd = process.cwd()) {
|
|
53
54
|
// 1. Check packageManager field in package.json
|
|
54
|
-
const fromPackageJson =
|
|
55
|
+
const fromPackageJson = PackageManagerDetector.detectFromPackageJson(cwd);
|
|
55
56
|
if (fromPackageJson) {
|
|
56
57
|
return fromPackageJson;
|
|
57
58
|
}
|
|
58
59
|
// 2. Check for lock files
|
|
59
|
-
const fromLockFile =
|
|
60
|
+
const fromLockFile = PackageManagerDetector.detectFromLockFiles(cwd);
|
|
60
61
|
if (fromLockFile) {
|
|
61
62
|
return fromLockFile;
|
|
62
63
|
}
|
|
@@ -68,12 +69,12 @@ class PackageManagerDetector {
|
|
|
68
69
|
* Detect from package.json packageManager field
|
|
69
70
|
*/
|
|
70
71
|
static detectFromPackageJson(cwd) {
|
|
71
|
-
const packageJsonPath = (0,
|
|
72
|
-
if (!(0,
|
|
72
|
+
const packageJsonPath = (0, node_path_1.join)(cwd, 'package.json');
|
|
73
|
+
if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
|
|
73
74
|
return null;
|
|
74
75
|
}
|
|
75
76
|
try {
|
|
76
|
-
const content = (0,
|
|
77
|
+
const content = (0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8');
|
|
77
78
|
const packageJson = JSON.parse(content);
|
|
78
79
|
if (packageJson.packageManager) {
|
|
79
80
|
// Parse format: "pnpm@10.28.1" or "npm@9.0.0+sha512.abc..."
|
|
@@ -84,7 +85,7 @@ class PackageManagerDetector {
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
|
-
catch
|
|
88
|
+
catch {
|
|
88
89
|
// Invalid package.json, continue to lock file detection
|
|
89
90
|
}
|
|
90
91
|
return null;
|
|
@@ -94,19 +95,19 @@ class PackageManagerDetector {
|
|
|
94
95
|
*/
|
|
95
96
|
static detectFromLockFiles(cwd) {
|
|
96
97
|
const lockFileChecks = [
|
|
97
|
-
{ pm: PACKAGE_MANAGERS.pnpm, path: (0,
|
|
98
|
-
{ pm: PACKAGE_MANAGERS.bun, path: (0,
|
|
98
|
+
{ pm: PACKAGE_MANAGERS.pnpm, path: (0, node_path_1.join)(cwd, 'pnpm-lock.yaml') },
|
|
99
|
+
{ pm: PACKAGE_MANAGERS.bun, path: (0, node_path_1.join)(cwd, 'bun.lockb') },
|
|
99
100
|
// Bun >= 1.2 writes a text `bun.lock` instead of the binary `bun.lockb`.
|
|
100
|
-
{ pm: PACKAGE_MANAGERS.bun, path: (0,
|
|
101
|
-
{ pm: PACKAGE_MANAGERS.yarn, path: (0,
|
|
102
|
-
{ pm: PACKAGE_MANAGERS.npm, path: (0,
|
|
101
|
+
{ pm: PACKAGE_MANAGERS.bun, path: (0, node_path_1.join)(cwd, 'bun.lock') },
|
|
102
|
+
{ pm: PACKAGE_MANAGERS.yarn, path: (0, node_path_1.join)(cwd, 'yarn.lock') },
|
|
103
|
+
{ pm: PACKAGE_MANAGERS.npm, path: (0, node_path_1.join)(cwd, 'package-lock.json') },
|
|
103
104
|
];
|
|
104
105
|
const existingLocks = lockFileChecks
|
|
105
|
-
.filter(({ path }) => (0,
|
|
106
|
+
.filter(({ path }) => (0, node_fs_1.existsSync)(path))
|
|
106
107
|
.map(({ pm, path }) => ({
|
|
107
108
|
pm,
|
|
108
109
|
path,
|
|
109
|
-
mtime: (0,
|
|
110
|
+
mtime: (0, node_fs_1.statSync)(path).mtime.getTime(),
|
|
110
111
|
}));
|
|
111
112
|
if (existingLocks.length === 0) {
|
|
112
113
|
return null;
|
|
@@ -131,20 +132,20 @@ class PackageManagerDetector {
|
|
|
131
132
|
static findWorkspaceRoot(cwd = process.cwd(), packageManager) {
|
|
132
133
|
const pmInfo = PACKAGE_MANAGERS[packageManager];
|
|
133
134
|
let currentDir = cwd;
|
|
134
|
-
while (currentDir !== (0,
|
|
135
|
+
while (currentDir !== (0, node_path_1.join)(currentDir, '..')) {
|
|
135
136
|
// Check for package manager-specific workspace file
|
|
136
137
|
if (pmInfo.workspaceFile) {
|
|
137
|
-
const workspaceFilePath = (0,
|
|
138
|
-
if ((0,
|
|
138
|
+
const workspaceFilePath = (0, node_path_1.join)(currentDir, pmInfo.workspaceFile);
|
|
139
|
+
if ((0, node_fs_1.existsSync)(workspaceFilePath)) {
|
|
139
140
|
return currentDir;
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
else {
|
|
143
144
|
// Check for package.json with workspaces field
|
|
144
|
-
const packageJsonPath = (0,
|
|
145
|
-
if ((0,
|
|
145
|
+
const packageJsonPath = (0, node_path_1.join)(currentDir, 'package.json');
|
|
146
|
+
if ((0, node_fs_1.existsSync)(packageJsonPath)) {
|
|
146
147
|
try {
|
|
147
|
-
const content = (0,
|
|
148
|
+
const content = (0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8');
|
|
148
149
|
const packageJson = JSON.parse(content);
|
|
149
150
|
// Check if workspaces field exists and is non-empty
|
|
150
151
|
if (packageJson.workspaces) {
|
|
@@ -159,12 +160,12 @@ class PackageManagerDetector {
|
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
|
-
catch
|
|
163
|
+
catch {
|
|
163
164
|
// Invalid package.json, continue searching
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
|
-
currentDir = (0,
|
|
168
|
+
currentDir = (0, node_path_1.join)(currentDir, '..');
|
|
168
169
|
}
|
|
169
170
|
return null;
|
|
170
171
|
}
|
|
@@ -172,7 +173,7 @@ class PackageManagerDetector {
|
|
|
172
173
|
* Check if directory is in a workspace
|
|
173
174
|
*/
|
|
174
175
|
static isInWorkspace(cwd, packageManager) {
|
|
175
|
-
return
|
|
176
|
+
return PackageManagerDetector.findWorkspaceRoot(cwd, packageManager) !== null;
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
exports.PackageManagerDetector = PackageManagerDetector;
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.fetchPackageVersions = fetchPackageVersions;
|
|
4
4
|
exports.clearPackageCache = clearPackageCache;
|
|
5
|
-
const undici_1 = require("undici");
|
|
6
|
-
const node_zlib_1 = require("node:zlib");
|
|
7
5
|
const node_util_1 = require("node:util");
|
|
6
|
+
const node_zlib_1 = require("node:zlib");
|
|
7
|
+
const undici_1 = require("undici");
|
|
8
8
|
const gunzipAsync = (0, node_util_1.promisify)(node_zlib_1.gunzip);
|
|
9
9
|
const inflateAsync = (0, node_util_1.promisify)(node_zlib_1.inflate);
|
|
10
10
|
const brotliDecompressAsync = (0, node_util_1.promisify)(node_zlib_1.brotliDecompress);
|
|
11
11
|
const config_1 = require("../config");
|
|
12
|
-
const registry_config_1 = require("./registry-config");
|
|
13
|
-
const versions_1 = require("../versions");
|
|
14
|
-
const retry_1 = require("../http/retry");
|
|
15
|
-
const inflight_1 = require("../http/inflight");
|
|
16
|
-
const resizable_semaphore_1 = require("../http/resizable-semaphore");
|
|
17
12
|
const adaptive_controller_1 = require("../http/adaptive-controller");
|
|
18
13
|
const etag_store_1 = require("../http/etag-store");
|
|
14
|
+
const inflight_1 = require("../http/inflight");
|
|
15
|
+
const resizable_semaphore_1 = require("../http/resizable-semaphore");
|
|
16
|
+
const retry_1 = require("../http/retry");
|
|
17
|
+
const versions_1 = require("../versions");
|
|
18
|
+
const registry_config_1 = require("./registry-config");
|
|
19
19
|
const inFlightLookups = new inflight_1.InflightMap();
|
|
20
20
|
// One pool per registry origin: scoped packages may resolve to different
|
|
21
21
|
// registries (`@scope:registry` in .npmrc), and each origin keeps its own
|
|
@@ -79,7 +79,7 @@ async function attemptRegistryFetch(target, path) {
|
|
|
79
79
|
'accept-encoding': 'gzip, deflate, br',
|
|
80
80
|
};
|
|
81
81
|
if (target.authHeader) {
|
|
82
|
-
requestHeaders
|
|
82
|
+
requestHeaders.authorization = target.authHeader;
|
|
83
83
|
}
|
|
84
84
|
if (cached) {
|
|
85
85
|
requestHeaders['if-none-match'] = cached.etag;
|
|
@@ -130,7 +130,7 @@ async function attemptRegistryFetch(target, path) {
|
|
|
130
130
|
}
|
|
131
131
|
const data = (0, versions_1.parseVersions)(decoded.toString('utf8'));
|
|
132
132
|
// Persist the ETag for next run's conditional request.
|
|
133
|
-
const etagHeader = headers
|
|
133
|
+
const etagHeader = headers.etag;
|
|
134
134
|
const etag = Array.isArray(etagHeader) ? etagHeader[0] : etagHeader;
|
|
135
135
|
if (etag) {
|
|
136
136
|
(0, etag_store_1.writeEtag)(cacheKey, etag.toString(), data);
|
|
@@ -232,8 +232,10 @@ async function fetchPackageVersions(packageNames, options = {}) {
|
|
|
232
232
|
const pendingEmissions = new Map();
|
|
233
233
|
let nextEmitIndex = 0;
|
|
234
234
|
const flushPending = () => {
|
|
235
|
-
while (
|
|
235
|
+
while (true) {
|
|
236
236
|
const ready = pendingEmissions.get(nextEmitIndex);
|
|
237
|
+
if (!ready)
|
|
238
|
+
break;
|
|
237
239
|
pendingEmissions.delete(nextEmitIndex);
|
|
238
240
|
options.onBatchReady?.(ready);
|
|
239
241
|
nextEmitIndex++;
|
|
@@ -82,7 +82,7 @@ exports.ConsoleUtils = {
|
|
|
82
82
|
clearProgress() {
|
|
83
83
|
if (!process.stderr.isTTY)
|
|
84
84
|
return;
|
|
85
|
-
process.stderr.write(
|
|
85
|
+
process.stderr.write(`\r${' '.repeat(exports.ConsoleUtils.LINE_WIDTH)}\r`);
|
|
86
86
|
},
|
|
87
87
|
};
|
|
88
88
|
//# sourceMappingURL=cursor.js.map
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.wrapPlainText = exports.truncatePlainText = exports.stripAnsi = exports.getVisualLength = exports.TerminalInput = exports.RAW_SHOW_CURSOR = exports.RAW_EXIT_ALT_SCREEN = exports.CursorUtils = exports.ConsoleUtils = exports.shouldDisableColor = exports.applyColorSetting = void 0;
|
|
4
|
+
var color_1 = require("./color");
|
|
5
|
+
Object.defineProperty(exports, "applyColorSetting", { enumerable: true, get: function () { return color_1.applyColorSetting; } });
|
|
6
|
+
Object.defineProperty(exports, "shouldDisableColor", { enumerable: true, get: function () { return color_1.shouldDisableColor; } });
|
|
4
7
|
var cursor_1 = require("./cursor");
|
|
5
|
-
Object.defineProperty(exports, "CursorUtils", { enumerable: true, get: function () { return cursor_1.CursorUtils; } });
|
|
6
8
|
Object.defineProperty(exports, "ConsoleUtils", { enumerable: true, get: function () { return cursor_1.ConsoleUtils; } });
|
|
9
|
+
Object.defineProperty(exports, "CursorUtils", { enumerable: true, get: function () { return cursor_1.CursorUtils; } });
|
|
7
10
|
Object.defineProperty(exports, "RAW_EXIT_ALT_SCREEN", { enumerable: true, get: function () { return cursor_1.RAW_EXIT_ALT_SCREEN; } });
|
|
8
11
|
Object.defineProperty(exports, "RAW_SHOW_CURSOR", { enumerable: true, get: function () { return cursor_1.RAW_SHOW_CURSOR; } });
|
|
9
12
|
var terminal_input_1 = require("./terminal-input");
|
|
@@ -13,7 +16,4 @@ Object.defineProperty(exports, "getVisualLength", { enumerable: true, get: funct
|
|
|
13
16
|
Object.defineProperty(exports, "stripAnsi", { enumerable: true, get: function () { return text_1.stripAnsi; } });
|
|
14
17
|
Object.defineProperty(exports, "truncatePlainText", { enumerable: true, get: function () { return text_1.truncatePlainText; } });
|
|
15
18
|
Object.defineProperty(exports, "wrapPlainText", { enumerable: true, get: function () { return text_1.wrapPlainText; } });
|
|
16
|
-
var color_1 = require("./color");
|
|
17
|
-
Object.defineProperty(exports, "applyColorSetting", { enumerable: true, get: function () { return color_1.applyColorSetting; } });
|
|
18
|
-
Object.defineProperty(exports, "shouldDisableColor", { enumerable: true, get: function () { return color_1.shouldDisableColor; } });
|
|
19
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -85,8 +85,12 @@ exports.TerminalInput = {
|
|
|
85
85
|
promptForImmediateConfirmation(prompt, defaultValue = true) {
|
|
86
86
|
return new Promise((resolve) => {
|
|
87
87
|
process.stdout.write(prompt);
|
|
88
|
-
// Replaced synchronously below before any keypress can call finish()
|
|
89
|
-
|
|
88
|
+
// Replaced synchronously below before any keypress can call finish(),
|
|
89
|
+
// so the placeholder body is unreachable. (The `v8 ignore next` form
|
|
90
|
+
// is not honored by coverage-v8 here; the block form is.)
|
|
91
|
+
/* v8 ignore start */
|
|
92
|
+
let cleanup = () => { };
|
|
93
|
+
/* v8 ignore stop */
|
|
90
94
|
const finish = (value) => {
|
|
91
95
|
cleanup();
|
|
92
96
|
process.stdout.write('\n');
|
|
@@ -7,10 +7,10 @@ exports.stripAnsi = stripAnsi;
|
|
|
7
7
|
exports.getVisualLength = getVisualLength;
|
|
8
8
|
exports.truncatePlainText = truncatePlainText;
|
|
9
9
|
exports.wrapPlainText = wrapPlainText;
|
|
10
|
+
const cli_truncate_1 = __importDefault(require("cli-truncate"));
|
|
10
11
|
const string_width_1 = __importDefault(require("string-width"));
|
|
11
12
|
const strip_ansi_1 = __importDefault(require("strip-ansi"));
|
|
12
13
|
const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
|
|
13
|
-
const cli_truncate_1 = __importDefault(require("cli-truncate"));
|
|
14
14
|
// Thin wrappers over the battle-tested terminal-string stack (string-width,
|
|
15
15
|
// strip-ansi, wrap-ansi, cli-truncate). The previous hand-rolled versions
|
|
16
16
|
// handled emoji but had no East Asian Width tables, so CJK text was counted at
|
|
@@ -15,6 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./domain"), exports);
|
|
18
|
-
__exportStar(require("./ui"), exports);
|
|
19
18
|
__exportStar(require("./streaming"), exports);
|
|
19
|
+
__exportStar(require("./ui"), exports);
|
|
20
20
|
//# sourceMappingURL=index.js.map
|
package/dist/shared/versions.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.parseVersions = parseVersions;
|
|
|
40
40
|
exports.isVersionOutdated = isVersionOutdated;
|
|
41
41
|
exports.getOptimizedRangeVersion = getOptimizedRangeVersion;
|
|
42
42
|
exports.findClosestMinorVersion = findClosestMinorVersion;
|
|
43
|
+
exports.findHighestPatchVersion = findHighestPatchVersion;
|
|
43
44
|
exports.applyVersionPrefix = applyVersionPrefix;
|
|
44
45
|
const semver = __importStar(require("semver"));
|
|
45
46
|
const manifest_1 = require("./manifest");
|
|
@@ -95,19 +96,9 @@ function isVersionOutdated(current, latest) {
|
|
|
95
96
|
*/
|
|
96
97
|
function getOptimizedRangeVersion(_packageName, currentRange, allVersions, latestVersion) {
|
|
97
98
|
try {
|
|
98
|
-
// Find the highest version that satisfies the current range
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return semver.satisfies(version, currentRange);
|
|
102
|
-
// semver.satisfies swallows invalid input internally (returns false);
|
|
103
|
-
// safety net for future semver behavior changes only.
|
|
104
|
-
/* v8 ignore start */
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
/* v8 ignore stop */
|
|
110
|
-
});
|
|
99
|
+
// Find the highest version that satisfies the current range. satisfies()
|
|
100
|
+
// returns false (never throws) for invalid input, so no guard is needed.
|
|
101
|
+
const satisfyingVersions = allVersions.filter((version) => semver.satisfies(version, currentRange));
|
|
111
102
|
if (satisfyingVersions.length === 0) {
|
|
112
103
|
return latestVersion;
|
|
113
104
|
}
|
|
@@ -130,7 +121,6 @@ function findClosestMinorVersion(installedVersion, allVersions) {
|
|
|
130
121
|
}
|
|
131
122
|
const installedMajor = semver.major(coercedInstalled);
|
|
132
123
|
const installedMinor = semver.minor(coercedInstalled);
|
|
133
|
-
const installedPatch = semver.patch(coercedInstalled);
|
|
134
124
|
let bestMinorVersion = null;
|
|
135
125
|
let bestMinorValue = -1;
|
|
136
126
|
// Single pass to find best minor version in same major
|
|
@@ -150,30 +140,44 @@ function findClosestMinorVersion(installedVersion, allVersions) {
|
|
|
150
140
|
if (bestMinorVersion) {
|
|
151
141
|
return bestMinorVersion;
|
|
152
142
|
}
|
|
153
|
-
// Fallback:
|
|
154
|
-
|
|
155
|
-
for (const version of allVersions) {
|
|
156
|
-
try {
|
|
157
|
-
const major = semver.major(version);
|
|
158
|
-
const minor = semver.minor(version);
|
|
159
|
-
const patch = semver.patch(version);
|
|
160
|
-
// Same major and minor, but higher patch
|
|
161
|
-
if (major === installedMajor && minor === installedMinor && patch > installedPatch) {
|
|
162
|
-
if (!bestPatchVersion || semver.gt(version, bestPatchVersion)) {
|
|
163
|
-
bestPatchVersion = version;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
// Skip invalid versions
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return bestPatchVersion;
|
|
143
|
+
// Fallback: highest patch version in the same major.minor that's higher than installed
|
|
144
|
+
return findHighestPatchVersion(installedVersion, allVersions);
|
|
172
145
|
}
|
|
173
146
|
catch {
|
|
174
147
|
return null;
|
|
175
148
|
}
|
|
176
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Find the highest patch version in the installed version's own major.minor line.
|
|
152
|
+
* This is the `--target patch` policy: never crosses a minor (or major) boundary.
|
|
153
|
+
*/
|
|
154
|
+
function findHighestPatchVersion(installedVersion, allVersions) {
|
|
155
|
+
const coercedInstalled = semver.coerce(installedVersion);
|
|
156
|
+
if (!coercedInstalled) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const installedMajor = semver.major(coercedInstalled);
|
|
160
|
+
const installedMinor = semver.minor(coercedInstalled);
|
|
161
|
+
const installedPatch = semver.patch(coercedInstalled);
|
|
162
|
+
let bestPatchVersion = null;
|
|
163
|
+
for (const version of allVersions) {
|
|
164
|
+
try {
|
|
165
|
+
const major = semver.major(version);
|
|
166
|
+
const minor = semver.minor(version);
|
|
167
|
+
const patch = semver.patch(version);
|
|
168
|
+
// Same major and minor, but higher patch
|
|
169
|
+
if (major === installedMajor && minor === installedMinor && patch > installedPatch) {
|
|
170
|
+
if (!bestPatchVersion || semver.gt(version, bestPatchVersion)) {
|
|
171
|
+
bestPatchVersion = version;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Skip invalid versions
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return bestPatchVersion;
|
|
180
|
+
}
|
|
177
181
|
/** Re-apply the original specifier's range prefix (^, ~, >=, …) to a new version. */
|
|
178
182
|
function applyVersionPrefix(originalSpecifier, targetVersion) {
|
|
179
183
|
const prefixMatch = originalSpecifier.match(/^([^\d]+)/);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inup",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.8",
|
|
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": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"ncu"
|
|
31
31
|
],
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"homepage": "https://github.
|
|
33
|
+
"homepage": "https://donfear.github.io/inup/",
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|
|
36
36
|
"url": "git+https://github.com/donfear/inup.git"
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"README.md"
|
|
44
44
|
],
|
|
45
45
|
"devDependencies": {
|
|
46
|
+
"@biomejs/biome": "^2.5.2",
|
|
46
47
|
"@types/node": "^25.9.4",
|
|
47
48
|
"@types/semver": "^7.7.1",
|
|
48
49
|
"@vitest/coverage-v8": "^4.1.9",
|
|
49
50
|
"dependency-cruiser": "^18.0.0",
|
|
50
|
-
"prettier": "^3.9.4",
|
|
51
51
|
"typescript": "^6.0.3",
|
|
52
52
|
"vitest": "^4.1.9"
|
|
53
53
|
},
|
|
@@ -73,8 +73,9 @@
|
|
|
73
73
|
"dev": "tsc --watch",
|
|
74
74
|
"start": "node dist/cli.js",
|
|
75
75
|
"link": "pnpm build && pnpm add -g .",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
76
|
+
"check": "biome check --write .",
|
|
77
|
+
"check:ci": "biome ci .",
|
|
78
|
+
"typecheck": "tsc --noEmit",
|
|
78
79
|
"demo:record": "bash docs/demo/record-demo.sh",
|
|
79
80
|
"demo:setup": "cd docs/demo-project && pnpm install",
|
|
80
81
|
"test": "vitest run",
|
|
@@ -82,6 +83,9 @@
|
|
|
82
83
|
"test:coverage": "vitest run --coverage --reporter=default --reporter=json --outputFile.json=coverage/test-results.json",
|
|
83
84
|
"lint:deps": "depcruise src --config .dependency-cruiser.cjs",
|
|
84
85
|
"docs:keys": "UPDATE_README=1 vitest run keymap-readme",
|
|
85
|
-
"docs:badges": "pnpm test:coverage && UPDATE_README=1 vitest run badges-readme"
|
|
86
|
+
"docs:badges": "pnpm test:coverage && UPDATE_README=1 vitest run badges-readme",
|
|
87
|
+
"site:dev": "pnpm --filter @inup/website dev",
|
|
88
|
+
"site:build": "pnpm --filter @inup/website build",
|
|
89
|
+
"site:preview": "pnpm --filter @inup/website preview"
|
|
86
90
|
}
|
|
87
91
|
}
|