@xaidenlabs/uso 1.1.3 → 1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaidenlabs/uso",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Universal Solana Orchestrator - A one-command setup tool for Solana and Anchor development environments on Windows, macOS, and Linux.",
5
5
  "bin": {
6
6
  "uso": "bin/index.js"
@@ -4,17 +4,6 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { log, spinner } = require('../utils/logger');
6
6
 
7
- /**
8
- * Adds a Windows Defender exclusion for a given path (requires elevation).
9
- * Returns true if successful.
10
- */
11
- const addDefenderExclusion = (dirPath) => {
12
- const normalized = dirPath.replace(/\//g, '\\');
13
- const cmd = `powershell -Command "Start-Process powershell -ArgumentList '-NoProfile', '-Command', 'Add-MpPreference -ExclusionPath \\\"${normalized}\\\"' -Verb RunAs -WindowStyle Hidden -Wait"`;
14
- const result = shell.exec(cmd, { silent: true });
15
- return result.code === 0;
16
- };
17
-
18
7
  const runProxyCommand = async (command, args = []) => {
19
8
  // Check if anchor is available
20
9
  if (!shell.which('anchor')) {
@@ -35,54 +24,29 @@ const runProxyCommand = async (command, args = []) => {
35
24
 
36
25
  const output = (execution.stderr || '') + (execution.stdout || '');
37
26
 
38
- // --- Error Detection & Auto-Fix ---
39
-
40
- // 1. Windows Defender / Application Control blocking build scripts (os error 4551)
41
- const isDefenderBlock = output.includes('os error 4551') || output.includes('Application Control policy has blocked');
42
- if (isDefenderBlock && os.platform() === 'win32') {
43
- log.warn("⚠️ Windows Defender is blocking Cargo build scripts.");
44
- log.info("🛡️ Adding project directory to Defender exclusions...\n");
45
-
46
- const cwd = process.cwd();
47
- const cargoHome = path.join(os.homedir(), '.cargo');
48
-
49
- const success = addDefenderExclusion(cwd) && addDefenderExclusion(cargoHome);
50
-
51
- if (success) {
52
- log.success("✅ Defender exclusions added.");
53
- log.info("🔄 Cleaning build cache and retrying...\n");
54
-
55
- // Clean stale blocked artifacts
56
- shell.exec('cargo clean', { silent: true });
27
+ // Detect Windows-specific errors that require elevation
28
+ const isPrivilegeError = output.includes('os error 1314') || output.includes('A required privilege is not held by the client');
29
+ const isAppControlBlock = output.includes('os error 4551') || output.includes('Application Control policy has blocked');
57
30
 
58
- // Retry the command
59
- const retry = shell.exec(fullCommand);
60
- if (retry.code === 0) {
61
- log.success(`✅ '${command}' completed successfully.`);
62
- } else {
63
- log.error(`❌ '${command}' still failed after adding exclusions.`);
64
- log.warn("👉 Try running your terminal as Administrator.");
65
- }
31
+ if ((isPrivilegeError || isAppControlBlock) && os.platform() === 'win32') {
32
+ if (isAppControlBlock) {
33
+ log.warn("⚠️ Windows Application Control is blocking Cargo build scripts.");
66
34
  } else {
67
- log.error(" Could not add Defender exclusions. Was the UAC prompt declined?");
68
- log.info("👉 Manually add exclusions in Windows Security > Virus & threat protection > Exclusions:");
69
- log.info(` - ${cwd}`);
70
- log.info(` - ${cargoHome}`);
35
+ log.warn("⚠️ Windows requires Administrator privileges for this operation.");
71
36
  }
72
- return;
73
- }
37
+ log.info("🔑 Requesting elevated access (build will run in background)...\n");
74
38
 
75
- // 2. Privilege error (os error 1314 — symlink creation requires elevation)
76
- const isPrivilegeError = output.includes('os error 1314') || output.includes('A required privilege is not held by the client');
77
- if (isPrivilegeError && os.platform() === 'win32') {
78
- log.warn("⚠️ Windows requires Administrator privileges for this operation.");
79
- log.info("🔑 Requesting elevated access...\n");
39
+ // Clean stale blocked artifacts before elevated retry
40
+ if (isAppControlBlock) {
41
+ const cleanSpin = spinner('Cleaning blocked build artifacts...').start();
42
+ shell.exec('cargo clean', { silent: true, cwd: process.cwd() });
43
+ cleanSpin.succeed('Build cache cleaned.');
44
+ }
80
45
 
81
46
  await runElevatedWithProgress(command, args);
82
- return;
47
+ } else {
48
+ log.error(`❌ '${command}' failed.`);
83
49
  }
84
-
85
- log.error(`❌ '${command}' failed.`);
86
50
  };
87
51
 
88
52
  /**
@@ -94,28 +58,40 @@ const runElevatedWithProgress = (command, args = []) => {
94
58
  return new Promise((resolve) => {
95
59
  const tmpDir = os.tmpdir();
96
60
  const ts = Date.now();
97
- const logFile = path.join(tmpDir, `uso-elevated-${ts}.log`);
98
- const doneFile = path.join(tmpDir, `uso-elevated-${ts}.done`);
99
- const cwd = process.cwd();
61
+ const logFile = path.join(tmpDir, `uso-elevated-${ts}.log`).replace(/\\/g, '\\\\');
62
+ const doneFile = path.join(tmpDir, `uso-elevated-${ts}.done`).replace(/\\/g, '\\\\');
63
+ const logFileNormal = path.join(tmpDir, `uso-elevated-${ts}.log`);
64
+ const doneFileNormal = path.join(tmpDir, `uso-elevated-${ts}.done`);
65
+ const cwd = process.cwd().replace(/\\/g, '\\\\');
100
66
 
101
67
  // Write an empty log file so we can start reading immediately
102
- fs.writeFileSync(logFile, '', 'utf8');
103
-
104
- const anchorCmd = `anchor ${command} ${args.join(' ')}`;
105
- const innerScript = `
106
- Set-Location '${cwd.replace(/'/g, "''")}';
107
- $output = & cmd /c '${anchorCmd} 2>&1';
108
- $output | Out-File -FilePath '${logFile.replace(/\\/g, '\\\\')}' -Encoding utf8 -Append;
109
- $LASTEXITCODE | Out-File -FilePath '${doneFile.replace(/\\/g, '\\\\')}' -Encoding utf8;
110
- `.replace(/\n/g, ' ').trim();
111
-
112
- // Launch hidden elevated process
113
- const elevateCmd = `powershell -Command "Start-Process powershell -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', '${innerScript.replace(/'/g, "''")}' -Verb RunAs -WindowStyle Hidden"`;
68
+ fs.writeFileSync(logFileNormal, '', 'utf8');
69
+
70
+ // Build a PowerShell script file to avoid quoting hell
71
+ const scriptFile = path.join(tmpDir, `uso-elevated-${ts}.ps1`);
72
+ const scriptContent = [
73
+ `Set-Location "${cwd}"`,
74
+ `$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")`,
75
+ `try {`,
76
+ ` anchor ${command} ${args.join(' ')} 2>&1 | Tee-Object -FilePath "${logFile}" -Append`,
77
+ ` $LASTEXITCODE | Out-File -FilePath "${doneFile}" -Encoding utf8`,
78
+ `} catch {`,
79
+ ` $_.Exception.Message | Out-File -FilePath "${logFile}" -Encoding utf8 -Append`,
80
+ ` "1" | Out-File -FilePath "${doneFile}" -Encoding utf8`,
81
+ `}`,
82
+ ].join('\n');
83
+
84
+ fs.writeFileSync(scriptFile, scriptContent, 'utf8');
85
+
86
+ // Launch hidden elevated process using the script file
87
+ const elevateCmd = `powershell -Command "Start-Process powershell -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', '${scriptFile.replace(/\\/g, '\\\\')}' -Verb RunAs -WindowStyle Hidden"`;
114
88
 
115
89
  const elevateResult = shell.exec(elevateCmd, { silent: true });
116
90
 
117
91
  if (elevateResult.code !== 0) {
118
92
  log.error("❌ Failed to launch elevated process. Was the UAC prompt declined?");
93
+ // Cleanup
94
+ try { fs.unlinkSync(scriptFile); } catch (e) { /* ignore */ }
119
95
  resolve();
120
96
  return;
121
97
  }
@@ -126,14 +102,17 @@ const runElevatedWithProgress = (command, args = []) => {
126
102
 
127
103
  const pollInterval = setInterval(() => {
128
104
  try {
129
- if (fs.existsSync(doneFile)) {
105
+ // Check if process finished
106
+ if (fs.existsSync(doneFileNormal)) {
130
107
  clearInterval(pollInterval);
131
108
 
132
- const exitCode = fs.readFileSync(doneFile, 'utf8').trim();
133
- const fullLog = fs.readFileSync(logFile, 'utf8');
109
+ const exitCode = fs.readFileSync(doneFileNormal, 'utf8').trim();
110
+ const fullLog = fs.readFileSync(logFileNormal, 'utf8');
134
111
 
135
- try { fs.unlinkSync(logFile); } catch (e) { /* ignore */ }
136
- try { fs.unlinkSync(doneFile); } catch (e) { /* ignore */ }
112
+ // Cleanup temp files
113
+ try { fs.unlinkSync(logFileNormal); } catch (e) { /* ignore */ }
114
+ try { fs.unlinkSync(doneFileNormal); } catch (e) { /* ignore */ }
115
+ try { fs.unlinkSync(scriptFile); } catch (e) { /* ignore */ }
137
116
 
138
117
  if (exitCode === '0') {
139
118
  spin.succeed(`'${command}' completed successfully (elevated).`);
@@ -141,6 +120,7 @@ const runElevatedWithProgress = (command, args = []) => {
141
120
  spin.fail(`'${command}' failed (elevated, exit code: ${exitCode}).`);
142
121
  }
143
122
 
123
+ // Print the captured output
144
124
  if (fullLog.trim()) {
145
125
  console.log('\n' + fullLog.trim());
146
126
  }
@@ -150,9 +130,9 @@ const runElevatedWithProgress = (command, args = []) => {
150
130
  }
151
131
 
152
132
  // Read new content for live progress
153
- const stats = fs.statSync(logFile);
133
+ const stats = fs.statSync(logFileNormal);
154
134
  if (stats.size > lastSize) {
155
- const content = fs.readFileSync(logFile, 'utf8');
135
+ const content = fs.readFileSync(logFileNormal, 'utf8');
156
136
  const lines = content.trim().split('\n').filter(l => l.trim());
157
137
  if (lines.length > 0) {
158
138
  const lastLine = lines[lines.length - 1].trim();
@@ -168,9 +148,10 @@ const runElevatedWithProgress = (command, args = []) => {
168
148
 
169
149
  // Safety timeout: 10 minutes
170
150
  setTimeout(() => {
171
- if (!fs.existsSync(doneFile)) {
151
+ if (!fs.existsSync(doneFileNormal)) {
172
152
  clearInterval(pollInterval);
173
153
  spin.fail("Timed out waiting for elevated process (10 min).");
154
+ try { fs.unlinkSync(scriptFile); } catch (e) { /* ignore */ }
174
155
  resolve();
175
156
  }
176
157
  }, 10 * 60 * 1000);