@uxmaltech/collab-cli 0.1.4 → 0.1.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.
- package/dist/commands/upgrade.js +1 -1
- package/dist/lib/npm-operations.js +47 -27
- package/package.json +1 -1
package/dist/commands/upgrade.js
CHANGED
|
@@ -39,7 +39,7 @@ Examples:
|
|
|
39
39
|
process.stdout.write(`Run ${(0, ansi_1.green)('collab upgrade')} to install the update.\n`);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
|
-
// ── Perform the upgrade
|
|
42
|
+
// ── Perform the upgrade ──────────────────────────────────────
|
|
43
43
|
const npmPath = (0, npm_operations_1.requireNpm)();
|
|
44
44
|
if (!npmPath) {
|
|
45
45
|
throw new errors_1.CliError('npm not found in PATH. Install Node.js/npm first.');
|
|
@@ -25,36 +25,56 @@ function requireNpm() {
|
|
|
25
25
|
*/
|
|
26
26
|
function npmGlobalInstall(npmPath, version) {
|
|
27
27
|
const spec = `${NPM_PACKAGE}@${version}`;
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!force && EEXIST_ERROR.test(message)) {
|
|
44
|
-
process.stderr.write('Retrying with --force to overwrite existing bin link...\n');
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (PERMISSION_ERROR.test(message)) {
|
|
48
|
-
process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Permission denied. Try:\n`) +
|
|
49
|
-
` sudo npm install -g ${spec}\n`);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Install failed: ${message}\n`));
|
|
53
|
-
}
|
|
28
|
+
// First attempt: pipe stderr so we can inspect it for EEXIST
|
|
29
|
+
try {
|
|
30
|
+
(0, node_child_process_1.execFileSync)(npmPath, ['install', '-g', spec], {
|
|
31
|
+
stdio: ['inherit', 'inherit', 'pipe'],
|
|
32
|
+
timeout: 60_000,
|
|
33
|
+
});
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch (firstError) {
|
|
37
|
+
// Extract stderr from the failed child process
|
|
38
|
+
const stderr = extractStderr(firstError);
|
|
39
|
+
if (!EEXIST_ERROR.test(stderr)) {
|
|
40
|
+
// Not an EEXIST error — report and bail
|
|
41
|
+
process.stderr.write(stderr);
|
|
42
|
+
reportInstallError(spec, firstError);
|
|
54
43
|
return false;
|
|
55
44
|
}
|
|
45
|
+
// EEXIST: bin symlink collision — retry with --force
|
|
46
|
+
process.stderr.write('Bin link conflict detected, retrying with --force...\n');
|
|
47
|
+
}
|
|
48
|
+
// Second attempt with --force (stdio: inherit for full visibility)
|
|
49
|
+
try {
|
|
50
|
+
(0, node_child_process_1.execFileSync)(npmPath, ['install', '-g', '--force', spec], {
|
|
51
|
+
stdio: 'inherit',
|
|
52
|
+
timeout: 60_000,
|
|
53
|
+
});
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
reportInstallError(spec, error);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function extractStderr(error) {
|
|
62
|
+
if (error && typeof error === 'object' && 'stderr' in error) {
|
|
63
|
+
const buf = error.stderr;
|
|
64
|
+
return typeof buf === 'string' ? buf : buf?.toString('utf8') ?? '';
|
|
65
|
+
}
|
|
66
|
+
return '';
|
|
67
|
+
}
|
|
68
|
+
function reportInstallError(spec, error) {
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
const stderr = extractStderr(error);
|
|
71
|
+
if (PERMISSION_ERROR.test(message) || PERMISSION_ERROR.test(stderr)) {
|
|
72
|
+
process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Permission denied. Try:\n`) +
|
|
73
|
+
` sudo npm install -g ${spec}\n`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Install failed: ${message}\n`));
|
|
56
77
|
}
|
|
57
|
-
return false;
|
|
58
78
|
}
|
|
59
79
|
/**
|
|
60
80
|
* Runs `npm uninstall -g @uxmaltech/collab-cli`.
|