beste-cli 0.1.0
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 +77 -0
- package/bin/index.js +141 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# beste-cli
|
|
2
|
+
|
|
3
|
+
Official CLI for [beste.co](https://ui.beste.co) - Install premium shadcn components with a single command.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/beste-cli)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## 🚀 Installation
|
|
9
|
+
|
|
10
|
+
Install globally to use `beste` command anywhere:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g beste-cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Or use with `npx` without installation:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx beste-cli add https://ui.beste.co/r/feature63
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 📦 Usage
|
|
23
|
+
|
|
24
|
+
### Add a Component
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
beste add https://ui.beste.co/r/feature63
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The CLI will:
|
|
31
|
+
|
|
32
|
+
- ✅ Fetch the component from beste.co
|
|
33
|
+
- ✅ Detect your project structure automatically
|
|
34
|
+
- ✅ Install files to the correct location
|
|
35
|
+
- ✅ Check for missing dependencies
|
|
36
|
+
- ✅ Offer to install missing packages
|
|
37
|
+
|
|
38
|
+
### Supported Package Managers
|
|
39
|
+
|
|
40
|
+
The CLI automatically detects and uses your preferred package manager:
|
|
41
|
+
|
|
42
|
+
- npm
|
|
43
|
+
- pnpm
|
|
44
|
+
- yarn
|
|
45
|
+
- bun
|
|
46
|
+
|
|
47
|
+
## 🛠️ How It Works
|
|
48
|
+
|
|
49
|
+
1. **Directory Detection**: The CLI checks for `components.json` and respects your aliases
|
|
50
|
+
2. **Component Fetching**: Downloads component data from beste.co
|
|
51
|
+
3. **File Installation**: Places files in the appropriate directory structure
|
|
52
|
+
4. **Dependency Check**: Compares required packages with your `package.json`
|
|
53
|
+
5. **Installation**: Offers to install missing dependencies with your package manager
|
|
54
|
+
|
|
55
|
+
## 📋 Requirements
|
|
56
|
+
|
|
57
|
+
- Node.js 18 or higher
|
|
58
|
+
- A React/Next.js project with shadcn/ui setup (recommended)
|
|
59
|
+
|
|
60
|
+
## 🤝 Contributing
|
|
61
|
+
|
|
62
|
+
Contributions are welcome! Please feel free to submit issues or pull requests.
|
|
63
|
+
|
|
64
|
+
## 📄 License
|
|
65
|
+
|
|
66
|
+
MIT © [compbyter](https://github.com/compbyter)
|
|
67
|
+
|
|
68
|
+
## 🔗 Links
|
|
69
|
+
|
|
70
|
+
- [Official Website](https://ui.beste.co)
|
|
71
|
+
- [GitHub Repository](https://github.com/compbyter/beste-cli)
|
|
72
|
+
- [npm Package](https://www.npmjs.com/package/beste-cli)
|
|
73
|
+
- [Report Issues](https://github.com/compbyter/beste-cli/issues)
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
Made with ❤️ for the beste.co community
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import { confirm } from '@inquirer/prompts';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
|
|
11
|
+
const program = new Command();
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.name('beste')
|
|
15
|
+
.description('beste.co Premium CLI')
|
|
16
|
+
.version('0.1.0');
|
|
17
|
+
|
|
18
|
+
async function getTargetDirectory() {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const componentsJsonPath = path.join(cwd, 'components.json');
|
|
21
|
+
const fallbackPath = path.join(cwd, 'src', 'components', 'beste');
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
if (await fs.pathExists(componentsJsonPath)) {
|
|
25
|
+
const config = await fs.readJson(componentsJsonPath);
|
|
26
|
+
const componentsAlias = config.aliases?.components;
|
|
27
|
+
|
|
28
|
+
if (componentsAlias) {
|
|
29
|
+
const cleanPath = componentsAlias.replace(/^[@~]\//, '');
|
|
30
|
+
const isUsingSrc = await fs.pathExists(path.join(cwd, 'src'));
|
|
31
|
+
return path.join(cwd, isUsingSrc ? 'src' : '', cleanPath, 'beste');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// Sessizce fallback'e geç
|
|
36
|
+
}
|
|
37
|
+
return fallbackPath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
program
|
|
41
|
+
.command('add <urlOrName>')
|
|
42
|
+
.description('Adds a new premium component to the project')
|
|
43
|
+
.action(async (urlOrName) => {
|
|
44
|
+
const spinner = ora(chalk.blue('Fetching component...')).start();
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
let componentData;
|
|
48
|
+
|
|
49
|
+
if (urlOrName.startsWith('http')) {
|
|
50
|
+
const response = await fetch(urlOrName);
|
|
51
|
+
if (!response.ok) throw new Error('Component not found at the provided URL!');
|
|
52
|
+
|
|
53
|
+
componentData = await response.json();
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error('Please use a full URL for now (e.g., https://ui.beste.co/r/footer9).');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!componentData.files || !Array.isArray(componentData.files)) {
|
|
59
|
+
throw new Error('Invalid component format. "files" array is missing.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const targetBaseDir = await getTargetDirectory();
|
|
63
|
+
|
|
64
|
+
for (const file of componentData.files) {
|
|
65
|
+
const fileName = path.basename(file.path);
|
|
66
|
+
|
|
67
|
+
let finalPath;
|
|
68
|
+
if (file.target) {
|
|
69
|
+
const targetSubDir = path.dirname(file.target).replace(/^components\//, '');
|
|
70
|
+
const fullTargetDir = path.join(targetBaseDir, '..', targetSubDir);
|
|
71
|
+
await fs.ensureDir(fullTargetDir);
|
|
72
|
+
finalPath = path.join(fullTargetDir, fileName);
|
|
73
|
+
} else {
|
|
74
|
+
await fs.ensureDir(targetBaseDir);
|
|
75
|
+
finalPath = path.join(targetBaseDir, fileName);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await fs.writeFile(finalPath, file.content);
|
|
79
|
+
|
|
80
|
+
const relativePath = path.relative(process.cwd(), finalPath);
|
|
81
|
+
spinner.succeed(chalk.green(`${fileName} added successfully!`));
|
|
82
|
+
console.log(chalk.gray(` └─ Location: ./${relativePath.replace(/\\/g, '/')}`));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// --- YENİ EKLENEN AKILLI BAĞIMLILIK KONTROLÜ ---
|
|
86
|
+
const allDependencies = [];
|
|
87
|
+
if (componentData.dependencies) allDependencies.push(...componentData.dependencies);
|
|
88
|
+
if (componentData.registryDependencies) allDependencies.push(...componentData.registryDependencies);
|
|
89
|
+
|
|
90
|
+
const uniqueDeps = [...new Set(allDependencies)];
|
|
91
|
+
|
|
92
|
+
if (uniqueDeps.length > 0) {
|
|
93
|
+
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
94
|
+
let missingDeps = uniqueDeps;
|
|
95
|
+
|
|
96
|
+
// Projenin package.json dosyasını oku ve yüklü olanları filtrele
|
|
97
|
+
if (await fs.pathExists(pkgPath)) {
|
|
98
|
+
const pkg = await fs.readJson(pkgPath);
|
|
99
|
+
const installedDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
100
|
+
missingDeps = uniqueDeps.filter(dep => !installedDeps[dep]);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (missingDeps.length > 0) {
|
|
104
|
+
console.log(chalk.yellow(`\n📦 These packages are missing: ${missingDeps.join(', ')}`));
|
|
105
|
+
|
|
106
|
+
// Kullanıcıya sor
|
|
107
|
+
const shouldInstall = await confirm({ message: 'Do you want to install these packages now?' });
|
|
108
|
+
|
|
109
|
+
if (shouldInstall) {
|
|
110
|
+
const installSpinner = ora('Installing packages...').start();
|
|
111
|
+
try {
|
|
112
|
+
// Paket yöneticisini akıllı tespit et
|
|
113
|
+
const cwd = process.cwd();
|
|
114
|
+
const isPnpm = await fs.pathExists(path.join(cwd, 'pnpm-lock.yaml'));
|
|
115
|
+
const isYarn = await fs.pathExists(path.join(cwd, 'yarn.lock'));
|
|
116
|
+
const isBun = await fs.pathExists(path.join(cwd, 'bun.lockb'));
|
|
117
|
+
|
|
118
|
+
const pmCommand = isPnpm ? 'pnpm add' : isYarn ? 'yarn add' : isBun ? 'bun add' : 'npm install';
|
|
119
|
+
|
|
120
|
+
// Kurulumu arka planda çalıştır
|
|
121
|
+
execSync(`${pmCommand} ${missingDeps.join(' ')}`, { stdio: 'pipe' });
|
|
122
|
+
installSpinner.succeed(chalk.green('Packages installed successfully! 🚀'));
|
|
123
|
+
} catch (error) {
|
|
124
|
+
installSpinner.fail(chalk.red('Failed to install packages.'));
|
|
125
|
+
console.log(chalk.white(`Please install manually: npm install ${missingDeps.join(' ')}`));
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
console.log(chalk.gray(`\nOkay, you can install them manually using this command:`));
|
|
129
|
+
console.log(chalk.white(` npm install ${missingDeps.join(' ')}`));
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
console.log(chalk.green(`\n✅ All required packages ( ${uniqueDeps.join(', ')} ) are already installed in the project!`));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
} catch (error) {
|
|
137
|
+
spinner.fail(chalk.red(`Error: ${error.message}`));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "beste-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for beste.co - Install offical beste.co components",
|
|
5
|
+
"author": "compbyter",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"beste": "bin/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/compbyter/beste-cli.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://ui.beste.co",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/compbyter/beste-cli/issues"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"cli",
|
|
28
|
+
"beste",
|
|
29
|
+
"beste.co",
|
|
30
|
+
"react",
|
|
31
|
+
"nextjs",
|
|
32
|
+
"ui",
|
|
33
|
+
"components",
|
|
34
|
+
"shadcn",
|
|
35
|
+
"shadcn-ui",
|
|
36
|
+
"premium-components",
|
|
37
|
+
"beste-ui",
|
|
38
|
+
"beste-components",
|
|
39
|
+
"beste-blocks",
|
|
40
|
+
"beste-cli"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@inquirer/prompts": "^7.10.1",
|
|
44
|
+
"chalk": "^5.6.2",
|
|
45
|
+
"commander": "^14.0.3",
|
|
46
|
+
"fs-extra": "^11.3.3",
|
|
47
|
+
"ora": "^9.3.0"
|
|
48
|
+
}
|
|
49
|
+
}
|