@uxmaltech/collab-cli 0.1.2 → 0.1.4

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.
@@ -17,8 +17,8 @@ function registerUpgradeCommand(program) {
17
17
  .option('--check', 'Only check for updates without installing')
18
18
  .addHelpText('after', `
19
19
  Examples:
20
- collab upgrade # Upgrade to the latest version
21
- collab upgrade --check # Check for updates without installing
20
+ collab upgrade # Upgrade to the latest version
21
+ collab upgrade --check # Check for updates without installing
22
22
  `)
23
23
  .action(async (options) => {
24
24
  const currentVersion = (0, version_1.readCliVersion)();
@@ -8,6 +8,7 @@ const ansi_1 = require("./ansi");
8
8
  const shell_1 = require("./shell");
9
9
  const NPM_PACKAGE = '@uxmaltech/collab-cli';
10
10
  const PERMISSION_ERROR = /EACCES|permission denied/i;
11
+ const EEXIST_ERROR = /EEXIST|file already exists/i;
11
12
  /**
12
13
  * Resolves the npm binary path or writes an error and returns null.
13
14
  */
@@ -24,24 +25,36 @@ function requireNpm() {
24
25
  */
25
26
  function npmGlobalInstall(npmPath, version) {
26
27
  const spec = `${NPM_PACKAGE}@${version}`;
27
- try {
28
- (0, node_child_process_1.execFileSync)(npmPath, ['install', '-g', spec], {
29
- stdio: 'inherit',
30
- timeout: 60_000,
31
- });
32
- return true;
33
- }
34
- catch (error) {
35
- const message = error instanceof Error ? error.message : String(error);
36
- if (PERMISSION_ERROR.test(message)) {
37
- process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Permission denied. Try:\n`) +
38
- ` sudo npm install -g ${spec}\n`);
28
+ // Try without --force first, then retry with --force on EEXIST
29
+ for (const force of [false, true]) {
30
+ try {
31
+ const args = force
32
+ ? ['install', '-g', '--force', spec]
33
+ : ['install', '-g', spec];
34
+ (0, node_child_process_1.execFileSync)(npmPath, args, {
35
+ stdio: 'inherit',
36
+ timeout: 60_000,
37
+ });
38
+ return true;
39
39
  }
40
- else {
41
- process.stderr.write((0, ansi_1.red)(`${ansi_1.CROSS} Install failed: ${message}\n`));
40
+ catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ // EEXIST: bin symlink collision — retry once with --force
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
+ }
54
+ return false;
42
55
  }
43
- return false;
44
56
  }
57
+ return false;
45
58
  }
46
59
  /**
47
60
  * Runs `npm uninstall -g @uxmaltech/collab-cli`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uxmaltech/collab-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for collaborative architecture and delivery workflows.",
5
5
  "private": false,
6
6
  "license": "UNLICENSED",