@xaidenlabs/uso 1.1.0 → 1.1.2
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/bin/index.js +1 -1
- package/package.json +1 -1
- package/src/commands/workflow.js +117 -4
- package/my-test-project/Anchor.toml +0 -18
- package/my-test-project/README.md +0 -36
- package/my-test-project/package-lock.json +0 -2102
- package/my-test-project/package.json +0 -17
- package/my-test-project/programs/my_test_project/Cargo.toml +0 -19
- package/my-test-project/programs/my_test_project/src/lib.rs +0 -16
- package/my-test-project/tests/my-test-project.ts +0 -16
- package/my-test-project/tsconfig.json +0 -17
- package/templates/default/programs/my-project/Cargo.lock +0 -1471
package/bin/index.js
CHANGED
package/package.json
CHANGED
package/src/commands/workflow.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const shell = require('shelljs');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
2
5
|
const { log, spinner } = require('../utils/logger');
|
|
3
6
|
|
|
4
7
|
const runProxyCommand = async (command, args = []) => {
|
|
@@ -16,20 +19,130 @@ const runProxyCommand = async (command, args = []) => {
|
|
|
16
19
|
|
|
17
20
|
if (execution.code === 0) {
|
|
18
21
|
log.success(`✅ '${command}' completed successfully.`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Check for Windows privilege error (os error 1314 — symlink creation requires elevation)
|
|
26
|
+
const output = (execution.stderr || '') + (execution.stdout || '');
|
|
27
|
+
const isPrivilegeError = output.includes('os error 1314') || output.includes('A required privilege is not held by the client');
|
|
28
|
+
|
|
29
|
+
if (isPrivilegeError && os.platform() === 'win32') {
|
|
30
|
+
log.warn("⚠️ Windows requires Administrator privileges for this operation.");
|
|
31
|
+
log.info("🔑 Requesting elevated access...\n");
|
|
32
|
+
|
|
33
|
+
await runElevatedWithProgress(command, args);
|
|
19
34
|
} else {
|
|
20
35
|
log.error(`❌ '${command}' failed.`);
|
|
21
|
-
// We don't exit process here strictly, but let the user know
|
|
22
36
|
}
|
|
23
37
|
};
|
|
24
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Runs the anchor command in a HIDDEN elevated PowerShell window,
|
|
41
|
+
* redirecting all output to a temp log file. The user's terminal
|
|
42
|
+
* shows a spinner that tails the log file in real-time.
|
|
43
|
+
*/
|
|
44
|
+
const runElevatedWithProgress = (command, args = []) => {
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
const tmpDir = os.tmpdir();
|
|
47
|
+
const logFile = path.join(tmpDir, `uso-elevated-${Date.now()}.log`);
|
|
48
|
+
const doneFile = path.join(tmpDir, `uso-elevated-${Date.now()}.done`);
|
|
49
|
+
const cwd = process.cwd();
|
|
50
|
+
|
|
51
|
+
// Write an empty log file so we can start reading immediately
|
|
52
|
+
fs.writeFileSync(logFile, '', 'utf8');
|
|
53
|
+
|
|
54
|
+
// Build the elevated command:
|
|
55
|
+
// 1. cd into the user's project directory
|
|
56
|
+
// 2. Run anchor <command>
|
|
57
|
+
// 3. Write exit code to a .done file so we know it finished
|
|
58
|
+
// 4. All stdout/stderr piped to the log file
|
|
59
|
+
const anchorCmd = `anchor ${command} ${args.join(' ')}`;
|
|
60
|
+
const innerScript = `
|
|
61
|
+
Set-Location '${cwd.replace(/'/g, "''")}';
|
|
62
|
+
$output = & cmd /c '${anchorCmd} 2>&1';
|
|
63
|
+
$output | Out-File -FilePath '${logFile.replace(/\\/g, '\\\\')}' -Encoding utf8 -Append;
|
|
64
|
+
$LASTEXITCODE | Out-File -FilePath '${doneFile.replace(/\\/g, '\\\\')}' -Encoding utf8;
|
|
65
|
+
`.replace(/\n/g, ' ').trim();
|
|
66
|
+
|
|
67
|
+
// Launch hidden elevated process
|
|
68
|
+
const elevateCmd = `powershell -Command "Start-Process powershell -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', '${innerScript.replace(/'/g, "''")}' -Verb RunAs -WindowStyle Hidden"`;
|
|
69
|
+
|
|
70
|
+
// This triggers the UAC prompt (that one still shows — it's Windows security, can't bypass it)
|
|
71
|
+
const elevateResult = shell.exec(elevateCmd, { silent: true });
|
|
72
|
+
|
|
73
|
+
if (elevateResult.code !== 0) {
|
|
74
|
+
log.error("❌ Failed to launch elevated process. Was the UAC prompt declined?");
|
|
75
|
+
resolve();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Now poll the log file and show progress
|
|
80
|
+
const spin = spinner('Building with elevated privileges...').start();
|
|
81
|
+
let lastSize = 0;
|
|
82
|
+
let lastLine = '';
|
|
83
|
+
|
|
84
|
+
const pollInterval = setInterval(() => {
|
|
85
|
+
try {
|
|
86
|
+
// Check if process finished
|
|
87
|
+
if (fs.existsSync(doneFile)) {
|
|
88
|
+
clearInterval(pollInterval);
|
|
89
|
+
|
|
90
|
+
const exitCode = fs.readFileSync(doneFile, 'utf8').trim();
|
|
91
|
+
const fullLog = fs.readFileSync(logFile, 'utf8');
|
|
92
|
+
|
|
93
|
+
// Cleanup temp files
|
|
94
|
+
try { fs.unlinkSync(logFile); } catch (e) { /* ignore */ }
|
|
95
|
+
try { fs.unlinkSync(doneFile); } catch (e) { /* ignore */ }
|
|
96
|
+
|
|
97
|
+
if (exitCode === '0') {
|
|
98
|
+
spin.succeed(`'${command}' completed successfully (elevated).`);
|
|
99
|
+
} else {
|
|
100
|
+
spin.fail(`'${command}' failed (elevated, exit code: ${exitCode}).`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Print the captured output
|
|
104
|
+
if (fullLog.trim()) {
|
|
105
|
+
console.log('\n' + fullLog.trim());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
resolve();
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Read new content from log file for progress
|
|
113
|
+
const stats = fs.statSync(logFile);
|
|
114
|
+
if (stats.size > lastSize) {
|
|
115
|
+
const content = fs.readFileSync(logFile, 'utf8');
|
|
116
|
+
const lines = content.trim().split('\n').filter(l => l.trim());
|
|
117
|
+
if (lines.length > 0) {
|
|
118
|
+
lastLine = lines[lines.length - 1].trim();
|
|
119
|
+
// Show the last meaningful line as spinner text
|
|
120
|
+
const displayLine = lastLine.length > 70 ? lastLine.substring(0, 67) + '...' : lastLine;
|
|
121
|
+
spin.text = displayLine;
|
|
122
|
+
}
|
|
123
|
+
lastSize = stats.size;
|
|
124
|
+
}
|
|
125
|
+
} catch (e) {
|
|
126
|
+
// File might not exist yet or be locked, just keep polling
|
|
127
|
+
}
|
|
128
|
+
}, 500);
|
|
129
|
+
|
|
130
|
+
// Safety timeout: 10 minutes max
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
if (!fs.existsSync(doneFile)) {
|
|
133
|
+
clearInterval(pollInterval);
|
|
134
|
+
spin.fail("Timed out waiting for elevated process (10 min).");
|
|
135
|
+
resolve();
|
|
136
|
+
}
|
|
137
|
+
}, 10 * 60 * 1000);
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
|
|
25
141
|
const build = () => runProxyCommand('build');
|
|
26
142
|
const test = () => runProxyCommand('test');
|
|
27
143
|
const deploy = () => runProxyCommand('deploy');
|
|
28
144
|
const clean = () => runProxyCommand('clean');
|
|
29
145
|
|
|
30
|
-
// Generic run command for other anchor commands?
|
|
31
|
-
// For now, explicit functions are safer for help generation.
|
|
32
|
-
|
|
33
146
|
module.exports = {
|
|
34
147
|
build,
|
|
35
148
|
test,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
[toolchain]
|
|
2
|
-
|
|
3
|
-
[features]
|
|
4
|
-
seeds = false
|
|
5
|
-
skip-lint = false
|
|
6
|
-
|
|
7
|
-
[programs.localnet]
|
|
8
|
-
my_test_project = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
|
|
9
|
-
|
|
10
|
-
[registry]
|
|
11
|
-
url = "https://api.apr.dev"
|
|
12
|
-
|
|
13
|
-
[provider]
|
|
14
|
-
cluster = "Localnet"
|
|
15
|
-
wallet = "~/.config/solana/id.json"
|
|
16
|
-
|
|
17
|
-
[scripts]
|
|
18
|
-
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Welcome to Your USO Project 🚀
|
|
2
|
-
|
|
3
|
-
Congratulations! You've just scaffolded a professional Solana workspace using the **Universal Solana Orchestrator (USO)**.
|
|
4
|
-
|
|
5
|
-
This isn't just a folder with files. It's a battle-tested setup ready for serious development.
|
|
6
|
-
|
|
7
|
-
## 📂 Structure
|
|
8
|
-
- `programs/`: Your Rust smart contracts live here.
|
|
9
|
-
- `tests/`: Robust TypeScript tests using Anchor.
|
|
10
|
-
- `Anchor.toml`: Your project configuration.
|
|
11
|
-
|
|
12
|
-
## ⚡ Quick Start
|
|
13
|
-
|
|
14
|
-
### 1. Build
|
|
15
|
-
Compile your smart contract:
|
|
16
|
-
```bash
|
|
17
|
-
anchor build
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### 2. Test
|
|
21
|
-
Run your test suite against a local validator:
|
|
22
|
-
```bash
|
|
23
|
-
anchor test
|
|
24
|
-
```
|
|
25
|
-
*Note: This automatically spins up a local validator, deploys your program, runs tests, and shuts down.*
|
|
26
|
-
|
|
27
|
-
### 3. Deploy (Devnet)
|
|
28
|
-
When you're ready to go public:
|
|
29
|
-
1. Switch to devnet: `solana config set --url devnet`
|
|
30
|
-
2. Airdrop SOL: `solana airdrop 2`
|
|
31
|
-
3. Deploy: `anchor deploy`
|
|
32
|
-
|
|
33
|
-
## 🧠 Need Help?
|
|
34
|
-
Run `uso doctor` if your environment feels weird. Usage instructions are also available via `uso help`.
|
|
35
|
-
|
|
36
|
-
Happy coding!
|