@xaidenlabs/uso 1.0.3 → 1.1.1

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 CHANGED
@@ -75,6 +75,23 @@ uso install anchor
75
75
 
76
76
  ---
77
77
 
78
+ ---
79
+
80
+ ### Project Scaffolding
81
+
82
+ Start a new project with a robust, pre-configured Anchor template.
83
+
84
+ ```bash
85
+ uso create <project-name>
86
+ ```
87
+
88
+ This generates a "batteries-included" workspace with:
89
+ - **Localnet Configuration**: `Anchor.toml` pre-wired for local development.
90
+ - **Test Suite**: A running example test file using the latest Anchor syntax.
91
+ - **Scripts**: NPM scripts for linting and testing.
92
+
93
+ ---
94
+
78
95
  ### Verification
79
96
 
80
97
  After installation, verify that all components are correctly configured and accessible in your system PATH.
package/bin/index.js CHANGED
@@ -3,6 +3,7 @@ const { program } = require('commander');
3
3
  const { init } = require('../src/commands/init');
4
4
  const { doctor } = require('../src/commands/doctor');
5
5
  const { verify } = require('../src/commands/verify');
6
+ const { create } = require('../src/commands/create');
6
7
  const { build, test, deploy, clean } = require('../src/commands/workflow');
7
8
  const { uninstall } = require('../src/commands/uninstall');
8
9
 
@@ -27,6 +28,11 @@ program
27
28
  .description('Verify installation by building a test Anchor project')
28
29
  .action(verify);
29
30
 
31
+ program
32
+ .command('create <project_name>')
33
+ .description('Scaffold a new Anchor project')
34
+ .action(create);
35
+
30
36
  program
31
37
  .command('build')
32
38
  .description('Build the Anchor project (wraps "anchor build")')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaidenlabs/uso",
3
- "version": "1.0.3",
3
+ "version": "1.1.1",
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"
@@ -0,0 +1,115 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const shell = require('shelljs');
4
+ const { log, spinner } = require('../utils/logger');
5
+ const { getCargoBinPath } = require('../utils/paths');
6
+
7
+ const create = async (projectName) => {
8
+ if (!projectName) {
9
+ log.error("❌ Please provide a project name: uso create <project-name>");
10
+ return;
11
+ }
12
+
13
+ // Validate project name (basic check for valid folder name)
14
+ if (!/^[a-z0-9-_]+$/.test(projectName)) {
15
+ log.error("❌ Project name can only contain lowercase letters, numbers, hyphens, and underscores.");
16
+ return;
17
+ }
18
+
19
+ const targetDir = path.resolve(process.cwd(), projectName);
20
+ if (fs.existsSync(targetDir)) {
21
+ log.error(`❌ Directory '${projectName}' already exists.`);
22
+ return;
23
+ }
24
+
25
+ log.header(`🏗️ Scaffolding new project: ${projectName}`);
26
+
27
+ // 1. Copy Template
28
+ const templateDir = path.resolve(__dirname, '../../templates/default');
29
+ const spin = spinner('Copying template files...').start();
30
+
31
+ try {
32
+ shell.cp('-R', templateDir, targetDir);
33
+ spin.succeed('Template copied.');
34
+ } catch (e) {
35
+ spin.fail('Failed to copy template.');
36
+ log.error(e.message);
37
+ return;
38
+ }
39
+
40
+ // 2. Customize Project (Rename files and content)
41
+ log.info("✏️ Customizing project details...");
42
+
43
+ // Rename programs/my-project to programs/<project-name>
44
+ // Note: Rust crate names typically use underscores, not hyphens.
45
+ const crateName = projectName.replace(/-/g, '_');
46
+
47
+ const oldProgramDir = path.join(targetDir, 'programs', 'my-project');
48
+ const newProgramDir = path.join(targetDir, 'programs', crateName);
49
+
50
+ // Rename tests/my-project.ts to tests/<project-name>.ts
51
+ const oldTestFile = path.join(targetDir, 'tests', 'my-project.ts');
52
+ const newTestFile = path.join(targetDir, 'tests', `${projectName}.ts`);
53
+
54
+ try {
55
+ if (fs.existsSync(oldProgramDir)) {
56
+ fs.renameSync(oldProgramDir, newProgramDir);
57
+ }
58
+ if (fs.existsSync(oldTestFile)) {
59
+ fs.renameSync(oldTestFile, newTestFile);
60
+ }
61
+
62
+ // Replace placeholders in files
63
+ const replaceInFile = (filePath, searchValue, replaceValue) => {
64
+ if (fs.existsSync(filePath)) {
65
+ let content = fs.readFileSync(filePath, 'utf8');
66
+ // Global replace
67
+ const regex = new RegExp(searchValue, 'g');
68
+ content = content.replace(regex, replaceValue);
69
+ fs.writeFileSync(filePath, content, 'utf8');
70
+ }
71
+ };
72
+
73
+ // Update Anchor.toml
74
+ replaceInFile(path.join(targetDir, 'Anchor.toml'), 'my_project', crateName);
75
+
76
+ // Update Cargo.toml
77
+ replaceInFile(path.join(newProgramDir, 'Cargo.toml'), 'my-project', projectName);
78
+ replaceInFile(path.join(newProgramDir, 'Cargo.toml'), 'my_project', crateName);
79
+
80
+ // Update lib.rs (if specific project name usage exists beyond mod name which is file-based in lib.rs typically, but here we defined inside lib.rs)
81
+ // Actually, in lib.rs: pub mod my_project -> pub mod crate_name
82
+ replaceInFile(path.join(newProgramDir, 'src', 'lib.rs'), 'my_project', crateName);
83
+
84
+ // Update test file
85
+ replaceInFile(newTestFile, 'my-project', projectName); // describe("my-project")
86
+ replaceInFile(newTestFile, 'my_project', crateName); // import ... "../target/types/my_project"
87
+
88
+ // Update class name in test file (MyProject -> ProjectNamePascalCase)
89
+ const toPascalCase = (str) => {
90
+ return str.match(/[a-z0-9]+/gi)
91
+ .map(word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase())
92
+ .join('');
93
+ };
94
+ const pascalName = toPascalCase(projectName);
95
+ replaceInFile(newTestFile, 'MyProject', pascalName);
96
+
97
+ } catch (e) {
98
+ log.error(`❌ Failed during customization: ${e.message}`);
99
+ // clean up? maybe not, let user see what happened
100
+ return;
101
+ }
102
+
103
+ // 4. Generate Keypair if needed?
104
+ // Anchor usually handles this on first build, but let's check if they have a wallet.
105
+ // We won't force it here, "uso init" or "uso verify" handles wallet creation.
106
+
107
+ log.header("\n🎉 Project Created Successfully!");
108
+ log.info(`\n👉 Next steps:\n`);
109
+ log.info(` cd ${projectName}`);
110
+ log.info(` npm install`);
111
+ log.info(` uso test`);
112
+ log.info(`\nHappy building! 🚀`);
113
+ };
114
+
115
+ module.exports = { create };
@@ -1,4 +1,5 @@
1
1
  const shell = require('shelljs');
2
+ const os = require('os');
2
3
  const { log, spinner } = require('../utils/logger');
3
4
 
4
5
  const runProxyCommand = async (command, args = []) => {
@@ -16,9 +17,29 @@ const runProxyCommand = async (command, args = []) => {
16
17
 
17
18
  if (execution.code === 0) {
18
19
  log.success(`✅ '${command}' completed successfully.`);
20
+ return;
21
+ }
22
+
23
+ // Check for Windows privilege error (os error 1314 — symlink creation requires elevation)
24
+ const output = (execution.stderr || '') + (execution.stdout || '');
25
+ const isPrivilegeError = output.includes('os error 1314') || output.includes('A required privilege is not held by the client');
26
+
27
+ if (isPrivilegeError && os.platform() === 'win32') {
28
+ log.warn("⚠️ Windows requires Administrator privileges for this operation.");
29
+ log.info("🔑 Requesting elevated access...");
30
+
31
+ const elevateCmd = `powershell -Command "Start-Process powershell -ArgumentList '-NoProfile', '-Command', 'cd \\"${process.cwd()}\\"; anchor ${command} ${args.join(' ')}; Read-Host \\"Press Enter to close\\"' -Verb RunAs -Wait"`;
32
+
33
+ const elevatedRun = shell.exec(elevateCmd);
34
+
35
+ if (elevatedRun.code === 0) {
36
+ log.success(`✅ '${command}' completed successfully (elevated).`);
37
+ } else {
38
+ log.error(`❌ '${command}' failed even with elevated privileges.`);
39
+ log.warn("👉 Try running your terminal as Administrator manually.");
40
+ }
19
41
  } else {
20
42
  log.error(`❌ '${command}' failed.`);
21
- // We don't exit process here strictly, but let the user know
22
43
  }
23
44
  };
24
45
 
@@ -27,9 +48,6 @@ const test = () => runProxyCommand('test');
27
48
  const deploy = () => runProxyCommand('deploy');
28
49
  const clean = () => runProxyCommand('clean');
29
50
 
30
- // Generic run command for other anchor commands?
31
- // For now, explicit functions are safer for help generation.
32
-
33
51
  module.exports = {
34
52
  build,
35
53
  test,
@@ -0,0 +1,18 @@
1
+ [toolchain]
2
+
3
+ [features]
4
+ seeds = false
5
+ skip-lint = false
6
+
7
+ [programs.localnet]
8
+ my_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"
@@ -0,0 +1,36 @@
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
+ uso build
18
+ ```
19
+
20
+ ### 2. Test
21
+ Run your test suite against a local validator:
22
+ ```bash
23
+ uso 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: `uso 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!
@@ -0,0 +1,19 @@
1
+ {
2
+ "scripts": {
3
+ "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
4
+ "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
5
+ },
6
+ "dependencies": {
7
+ "@coral-xyz/anchor": "^0.32.1"
8
+ },
9
+ "devDependencies": {
10
+ "chai": "^4.3.7",
11
+ "mocha": "^9.0.3",
12
+ "ts-mocha": "^10.0.0",
13
+ "@types/mocha": "^9.0.0",
14
+ "@types/chai": "^4.3.0",
15
+ "@types/node": "^16.0.0",
16
+ "typescript": "^4.3.5",
17
+ "prettier": "^2.6.2"
18
+ }
19
+ }