@zhin.js/cli 1.0.7 → 1.0.8
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/CHANGELOG.md +6 -0
- package/lib/cli.js +8 -0
- package/lib/cli.js.map +1 -1
- package/lib/commands/install.d.ts +4 -0
- package/lib/commands/install.d.ts.map +1 -0
- package/lib/commands/install.js +209 -0
- package/lib/commands/install.js.map +1 -0
- package/lib/commands/new.d.ts.map +1 -1
- package/lib/commands/new.js +70 -66
- package/lib/commands/new.js.map +1 -1
- package/lib/commands/pub.d.ts +3 -0
- package/lib/commands/pub.d.ts.map +1 -0
- package/lib/commands/pub.js +151 -0
- package/lib/commands/pub.js.map +1 -0
- package/lib/commands/search.d.ts +4 -0
- package/lib/commands/search.d.ts.map +1 -0
- package/lib/commands/search.js +205 -0
- package/lib/commands/search.js.map +1 -0
- package/package.json +1 -1
- package/src/cli.ts +8 -0
- package/src/commands/install.ts +242 -0
- package/src/commands/new.ts +76 -73
- package/src/commands/pub.ts +176 -0
- package/src/commands/search.ts +243 -0
- package/tsconfig.json +17 -11
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
export const pubCommand = new Command('pub')
|
|
8
|
+
.description('发布插件到 npm')
|
|
9
|
+
.argument('[plugin-name]', '插件名称(如: my-plugin)')
|
|
10
|
+
.option('--tag <tag>', '发布标签', 'latest')
|
|
11
|
+
.option('--access <access>', '访问级别 (public|restricted)', 'public')
|
|
12
|
+
.option('--registry <url>', '自定义 npm registry')
|
|
13
|
+
.option('--dry-run', '试运行,不实际发布', false)
|
|
14
|
+
.option('--skip-build', '跳过构建步骤', false)
|
|
15
|
+
.action(async (pluginName, options) => {
|
|
16
|
+
try {
|
|
17
|
+
const pluginsDir = path.resolve(process.cwd(), 'plugins');
|
|
18
|
+
// 检查 plugins 目录是否存在
|
|
19
|
+
if (!fs.existsSync(pluginsDir)) {
|
|
20
|
+
logger.error('未找到 plugins 目录,请在项目根目录运行此命令');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
// 获取所有插件
|
|
24
|
+
const availablePlugins = fs.readdirSync(pluginsDir)
|
|
25
|
+
.filter(name => {
|
|
26
|
+
const pluginPath = path.join(pluginsDir, name);
|
|
27
|
+
return fs.statSync(pluginPath).isDirectory() &&
|
|
28
|
+
fs.existsSync(path.join(pluginPath, 'package.json'));
|
|
29
|
+
});
|
|
30
|
+
if (availablePlugins.length === 0) {
|
|
31
|
+
logger.error('未找到可发布的插件');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
// 如果没有指定插件名,让用户选择
|
|
35
|
+
let selectedPlugin = pluginName;
|
|
36
|
+
if (!selectedPlugin) {
|
|
37
|
+
if (availablePlugins.length === 1) {
|
|
38
|
+
selectedPlugin = availablePlugins[0];
|
|
39
|
+
logger.info(`自动选择插件: ${selectedPlugin}`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
const { plugin } = await inquirer.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: 'list',
|
|
45
|
+
name: 'plugin',
|
|
46
|
+
message: '请选择要发布的插件:',
|
|
47
|
+
choices: availablePlugins
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
selectedPlugin = plugin;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 验证插件是否存在
|
|
54
|
+
const pluginDir = path.join(pluginsDir, selectedPlugin);
|
|
55
|
+
if (!fs.existsSync(pluginDir)) {
|
|
56
|
+
logger.error(`插件不存在: ${selectedPlugin}`);
|
|
57
|
+
logger.log(`可用插件: ${availablePlugins.join(', ')}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
const packageJsonPath = path.join(pluginDir, 'package.json');
|
|
61
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
62
|
+
logger.error(`未找到 package.json: ${packageJsonPath}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
// 读取 package.json
|
|
66
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
67
|
+
const packageName = packageJson.name;
|
|
68
|
+
const version = packageJson.version;
|
|
69
|
+
logger.info(`准备发布插件: ${packageName}@${version}`);
|
|
70
|
+
logger.log('');
|
|
71
|
+
// 确认发布
|
|
72
|
+
if (!options.dryRun) {
|
|
73
|
+
const { confirm } = await inquirer.prompt([
|
|
74
|
+
{
|
|
75
|
+
type: 'confirm',
|
|
76
|
+
name: 'confirm',
|
|
77
|
+
message: `确认发布 ${packageName}@${version} 到 npm?`,
|
|
78
|
+
default: false
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
if (!confirm) {
|
|
82
|
+
logger.warn('已取消发布');
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 构建插件
|
|
87
|
+
if (!options.skipBuild) {
|
|
88
|
+
logger.info('正在构建插件...');
|
|
89
|
+
try {
|
|
90
|
+
execSync('pnpm build', {
|
|
91
|
+
cwd: pluginDir,
|
|
92
|
+
stdio: 'inherit'
|
|
93
|
+
});
|
|
94
|
+
logger.success('✓ 构建完成');
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
logger.error('构建失败');
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// 构建 npm publish 命令
|
|
102
|
+
const publishArgs = ['publish'];
|
|
103
|
+
if (options.access) {
|
|
104
|
+
publishArgs.push('--access', options.access);
|
|
105
|
+
}
|
|
106
|
+
if (options.tag) {
|
|
107
|
+
publishArgs.push('--tag', options.tag);
|
|
108
|
+
}
|
|
109
|
+
if (options.registry) {
|
|
110
|
+
publishArgs.push('--registry', options.registry);
|
|
111
|
+
}
|
|
112
|
+
if (options.dryRun) {
|
|
113
|
+
publishArgs.push('--dry-run');
|
|
114
|
+
}
|
|
115
|
+
// 总是添加 --no-git-checks(因为 plugins 可能不是 git 根目录)
|
|
116
|
+
publishArgs.push('--no-git-checks');
|
|
117
|
+
// 发布插件
|
|
118
|
+
logger.info(`正在发布${options.dryRun ? '(试运行)' : ''}...`);
|
|
119
|
+
logger.log(`命令: pnpm ${publishArgs.join(' ')}`);
|
|
120
|
+
logger.log('');
|
|
121
|
+
try {
|
|
122
|
+
execSync(`pnpm ${publishArgs.join(' ')}`, {
|
|
123
|
+
cwd: pluginDir,
|
|
124
|
+
stdio: 'inherit'
|
|
125
|
+
});
|
|
126
|
+
if (options.dryRun) {
|
|
127
|
+
logger.success('✓ 试运行完成');
|
|
128
|
+
logger.log('');
|
|
129
|
+
logger.log('💡 提示: 移除 --dry-run 参数以实际发布');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
logger.success(`✓ ${packageName}@${version} 发布成功!`);
|
|
133
|
+
logger.log('');
|
|
134
|
+
logger.log('📦 安装命令:');
|
|
135
|
+
logger.log(` pnpm add ${packageName}`);
|
|
136
|
+
logger.log('');
|
|
137
|
+
logger.log('🔗 npm 链接:');
|
|
138
|
+
logger.log(` https://www.npmjs.com/package/${packageName}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
logger.error('发布失败');
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
logger.error(`发布失败: ${error.message}`);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=pub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pub.js","sourceRoot":"","sources":["../../src/commands/pub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,aAAa,SAyItB,CAAC;AAEL,eAAO,MAAM,WAAW,SA4FpB,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import { execSync } from 'node:child_process';
|
|
4
|
+
export const searchCommand = new Command('search')
|
|
5
|
+
.description('搜索 Zhin.js 插件')
|
|
6
|
+
.argument('[keyword]', '搜索关键词')
|
|
7
|
+
.option('-c, --category <category>', '按分类搜索 (utility|service|game|adapter|admin|ai)')
|
|
8
|
+
.option('-l, --limit <number>', '限制结果数量', '20')
|
|
9
|
+
.option('--official', '仅显示官方插件', false)
|
|
10
|
+
.action(async (keyword, options) => {
|
|
11
|
+
try {
|
|
12
|
+
logger.info('正在搜索插件...');
|
|
13
|
+
logger.log('');
|
|
14
|
+
// 构建搜索查询
|
|
15
|
+
let searchQuery = 'zhin';
|
|
16
|
+
if (options.official) {
|
|
17
|
+
searchQuery = '@zhin.js';
|
|
18
|
+
}
|
|
19
|
+
else if (keyword) {
|
|
20
|
+
searchQuery = `zhin.js ${keyword} `;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
searchQuery = 'zhin.js plugin';
|
|
24
|
+
}
|
|
25
|
+
// 使用 npm search
|
|
26
|
+
const cmd = `npm search ${searchQuery} --json`;
|
|
27
|
+
try {
|
|
28
|
+
const output = execSync(cmd, {
|
|
29
|
+
encoding: 'utf-8',
|
|
30
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
31
|
+
stdio: ['pipe', 'pipe', 'ignore'] // 忽略 stderr
|
|
32
|
+
});
|
|
33
|
+
const results = JSON.parse(output);
|
|
34
|
+
// 过滤结果
|
|
35
|
+
let filteredResults = results.filter((pkg) => {
|
|
36
|
+
// 必须包含 zhin 关键词
|
|
37
|
+
const keywords = pkg.keywords || [];
|
|
38
|
+
const hasZhin = keywords.includes('zhin') ||
|
|
39
|
+
keywords.includes('plugin') ||
|
|
40
|
+
pkg.name.startsWith('@zhin.js/') ||
|
|
41
|
+
pkg.name.startsWith('zhin.js-');
|
|
42
|
+
if (!hasZhin)
|
|
43
|
+
return false;
|
|
44
|
+
// 按分类过滤
|
|
45
|
+
if (options.category) {
|
|
46
|
+
const category = pkg.keywords?.find((k) => k.includes(options.category));
|
|
47
|
+
if (!category)
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// 按关键词过滤
|
|
51
|
+
if (keyword) {
|
|
52
|
+
const searchIn = [
|
|
53
|
+
pkg.name,
|
|
54
|
+
pkg.description || '',
|
|
55
|
+
...(pkg.keywords || [])
|
|
56
|
+
].join(' ').toLowerCase();
|
|
57
|
+
return searchIn.includes(keyword.toLowerCase());
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
});
|
|
61
|
+
// 限制结果数量
|
|
62
|
+
const limit = parseInt(String(options.limit) || '20');
|
|
63
|
+
if (filteredResults.length > limit) {
|
|
64
|
+
filteredResults = filteredResults.slice(0, limit);
|
|
65
|
+
}
|
|
66
|
+
// 显示结果
|
|
67
|
+
if (filteredResults.length === 0) {
|
|
68
|
+
logger.warn('未找到匹配的插件');
|
|
69
|
+
logger.log('');
|
|
70
|
+
logger.log('💡 提示:');
|
|
71
|
+
logger.log(' - 尝试使用不同的关键词');
|
|
72
|
+
logger.log(' - 访问插件市场: https://zhin.pages.dev/plugins');
|
|
73
|
+
logger.log(' - 在 GitHub 搜索: https://github.com/topics/zhin.js');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
logger.success(`找到 ${filteredResults.length} 个插件:`);
|
|
77
|
+
logger.log('');
|
|
78
|
+
// 按下载量排序
|
|
79
|
+
filteredResults.sort((a, b) => {
|
|
80
|
+
const aDownloads = parseInt(a.downloads || '0');
|
|
81
|
+
const bDownloads = parseInt(b.downloads || '0');
|
|
82
|
+
return bDownloads - aDownloads;
|
|
83
|
+
});
|
|
84
|
+
// 显示插件列表
|
|
85
|
+
filteredResults.forEach((pkg, index) => {
|
|
86
|
+
const name = pkg.name;
|
|
87
|
+
const version = pkg.version;
|
|
88
|
+
const description = pkg.description || '无描述';
|
|
89
|
+
const author = pkg.publisher?.username || '未知';
|
|
90
|
+
const date = pkg.date ? new Date(pkg.date).toLocaleDateString('zh-CN') : '未知';
|
|
91
|
+
// 判断插件类型
|
|
92
|
+
let badge = '';
|
|
93
|
+
if (name.startsWith('@zhin.js/')) {
|
|
94
|
+
badge = '✨ [官方]';
|
|
95
|
+
}
|
|
96
|
+
else if (name.startsWith('zhin.js-')) {
|
|
97
|
+
badge = '📦 [社区]';
|
|
98
|
+
}
|
|
99
|
+
logger.log(`${index + 1}. ${badge} ${name}@${version}`);
|
|
100
|
+
logger.log(` ${description}`);
|
|
101
|
+
logger.log(` 作者: ${author} | 更新: ${date}`);
|
|
102
|
+
// 显示安装命令
|
|
103
|
+
logger.log(` 安装: zhin install ${name}`);
|
|
104
|
+
logger.log('');
|
|
105
|
+
});
|
|
106
|
+
logger.log('💡 提示:');
|
|
107
|
+
logger.log(' - 使用 zhin info <package> 查看插件详情');
|
|
108
|
+
logger.log(' - 使用 zhin install <package> 安装插件');
|
|
109
|
+
logger.log(' - 访问 https://zhin.pages.dev/plugins 查看完整列表');
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.error('搜索失败,请检查网络连接');
|
|
113
|
+
logger.log('');
|
|
114
|
+
logger.log('💡 替代方案:');
|
|
115
|
+
logger.log(' - 访问 npm: https://www.npmjs.com/search?q=zhin.js');
|
|
116
|
+
logger.log(' - 访问 GitHub: https://github.com/topics/zhin.js');
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logger.error(`搜索插件失败: ${error.message}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
export const infoCommand = new Command('info')
|
|
126
|
+
.description('查看插件详细信息')
|
|
127
|
+
.argument('<package>', '插件包名')
|
|
128
|
+
.action(async (packageName) => {
|
|
129
|
+
try {
|
|
130
|
+
logger.info(`正在获取 ${packageName} 的信息...`);
|
|
131
|
+
logger.log('');
|
|
132
|
+
const cmd = `npm view ${packageName} --json`;
|
|
133
|
+
try {
|
|
134
|
+
const output = execSync(cmd, {
|
|
135
|
+
encoding: 'utf-8',
|
|
136
|
+
stdio: ['pipe', 'pipe', 'ignore']
|
|
137
|
+
});
|
|
138
|
+
const info = JSON.parse(output);
|
|
139
|
+
// 显示插件信息
|
|
140
|
+
logger.success('插件信息:');
|
|
141
|
+
logger.log('');
|
|
142
|
+
logger.log(`📦 名称: ${info.name}`);
|
|
143
|
+
logger.log(`📝 版本: ${info.version}`);
|
|
144
|
+
logger.log(`📄 描述: ${info.description || '无'}`);
|
|
145
|
+
logger.log(`👤 作者: ${info.author?.name || info.maintainers?.[0]?.name || '未知'}`);
|
|
146
|
+
logger.log(`📅 发布时间: ${new Date(info.time?.modified || info.time?.created).toLocaleDateString('zh-CN')}`);
|
|
147
|
+
if (info.keywords?.length > 0) {
|
|
148
|
+
logger.log(`🏷️ 标签: ${info.keywords.join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
if (info.homepage) {
|
|
151
|
+
logger.log(`🏠 主页: ${info.homepage}`);
|
|
152
|
+
}
|
|
153
|
+
if (info.repository?.url) {
|
|
154
|
+
logger.log(`📂 仓库: ${info.repository.url.replace(/^git\+/, '').replace(/\.git$/, '')}`);
|
|
155
|
+
}
|
|
156
|
+
if (info.bugs?.url) {
|
|
157
|
+
logger.log(`🐛 问题: ${info.bugs.url}`);
|
|
158
|
+
}
|
|
159
|
+
if (info.license) {
|
|
160
|
+
logger.log(`⚖️ 许可: ${info.license}`);
|
|
161
|
+
}
|
|
162
|
+
// 显示依赖
|
|
163
|
+
if (info.peerDependencies) {
|
|
164
|
+
logger.log('');
|
|
165
|
+
logger.log('🔗 对等依赖:');
|
|
166
|
+
Object.entries(info.peerDependencies).forEach(([dep, ver]) => {
|
|
167
|
+
logger.log(` ${dep}: ${ver}`);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// 显示安装命令
|
|
171
|
+
logger.log('');
|
|
172
|
+
logger.log('📥 安装命令:');
|
|
173
|
+
logger.log(` zhin install ${info.name}`);
|
|
174
|
+
logger.log(` # 或`);
|
|
175
|
+
logger.log(` pnpm add ${info.name}`);
|
|
176
|
+
// Zhin 特定信息
|
|
177
|
+
if (info.zhin) {
|
|
178
|
+
logger.log('');
|
|
179
|
+
logger.log('🎯 Zhin 信息:');
|
|
180
|
+
if (info.zhin.displayName) {
|
|
181
|
+
logger.log(` 显示名称: ${info.zhin.displayName}`);
|
|
182
|
+
}
|
|
183
|
+
if (info.zhin.category) {
|
|
184
|
+
logger.log(` 分类: ${info.zhin.category}`);
|
|
185
|
+
}
|
|
186
|
+
if (info.zhin.features?.length > 0) {
|
|
187
|
+
logger.log(` 功能: ${info.zhin.features.join(', ')}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
logger.error(`未找到插件: ${packageName}`);
|
|
193
|
+
logger.log('');
|
|
194
|
+
logger.log('💡 提示:');
|
|
195
|
+
logger.log(' - 检查插件名称是否正确');
|
|
196
|
+
logger.log(' - 使用 zhin search 搜索插件');
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
logger.error(`获取插件信息失败: ${error.message}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -6,6 +6,9 @@ import { stopCommand } from './commands/stop.js';
|
|
|
6
6
|
import { devCommand } from './commands/dev.js';
|
|
7
7
|
import { buildCommand } from './commands/build.js';
|
|
8
8
|
import { newCommand } from './commands/new.js';
|
|
9
|
+
import { pubCommand } from './commands/pub.js';
|
|
10
|
+
import { installCommand, addCommand } from './commands/install.js';
|
|
11
|
+
import { searchCommand, infoCommand } from './commands/search.js';
|
|
9
12
|
|
|
10
13
|
const program = new Command();
|
|
11
14
|
|
|
@@ -21,5 +24,10 @@ program.addCommand(stopCommand);
|
|
|
21
24
|
program.addCommand(devCommand);
|
|
22
25
|
program.addCommand(buildCommand);
|
|
23
26
|
program.addCommand(newCommand);
|
|
27
|
+
program.addCommand(pubCommand);
|
|
28
|
+
program.addCommand(installCommand);
|
|
29
|
+
program.addCommand(addCommand);
|
|
30
|
+
program.addCommand(searchCommand);
|
|
31
|
+
program.addCommand(infoCommand);
|
|
24
32
|
|
|
25
33
|
program.parse();
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
interface InstallOptions {
|
|
9
|
+
save?: boolean;
|
|
10
|
+
saveDev?: boolean;
|
|
11
|
+
global?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const installCommand = new Command('install')
|
|
15
|
+
.description('安装插件(npm 包或 git 仓库)')
|
|
16
|
+
.argument('[plugin]', '插件名称或 git 地址')
|
|
17
|
+
.option('-S, --save', '安装到 dependencies(默认)', true)
|
|
18
|
+
.option('-D, --save-dev', '安装到 devDependencies', false)
|
|
19
|
+
.option('-g, --global', '全局安装', false)
|
|
20
|
+
.action(async (plugin: string, options: InstallOptions) => {
|
|
21
|
+
try {
|
|
22
|
+
let pluginToInstall = plugin;
|
|
23
|
+
|
|
24
|
+
// 如果没有指定插件,交互式输入
|
|
25
|
+
if (!pluginToInstall) {
|
|
26
|
+
const { input } = await inquirer.prompt([
|
|
27
|
+
{
|
|
28
|
+
type: 'input',
|
|
29
|
+
name: 'input',
|
|
30
|
+
message: '请输入插件名称或 git 地址:',
|
|
31
|
+
validate: (input: string) => {
|
|
32
|
+
if (!input.trim()) {
|
|
33
|
+
return '插件名称或地址不能为空';
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
pluginToInstall = input;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 判断插件类型
|
|
43
|
+
const pluginType = detectPluginType(pluginToInstall);
|
|
44
|
+
|
|
45
|
+
logger.info(`检测到插件类型: ${pluginType}`);
|
|
46
|
+
logger.info(`正在安装: ${pluginToInstall}`);
|
|
47
|
+
logger.log('');
|
|
48
|
+
|
|
49
|
+
// 构建安装命令
|
|
50
|
+
const installCmd = buildInstallCommand(pluginToInstall, pluginType, options);
|
|
51
|
+
|
|
52
|
+
logger.log(`执行命令: ${installCmd}`);
|
|
53
|
+
logger.log('');
|
|
54
|
+
|
|
55
|
+
// 执行安装
|
|
56
|
+
try {
|
|
57
|
+
execSync(installCmd, {
|
|
58
|
+
cwd: process.cwd(),
|
|
59
|
+
stdio: 'inherit'
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
logger.success('✓ 插件安装成功!');
|
|
63
|
+
logger.log('');
|
|
64
|
+
|
|
65
|
+
// 如果是 git 插件,提供额外说明
|
|
66
|
+
if (pluginType === 'git') {
|
|
67
|
+
logger.log('📝 Git 插件已安装到 node_modules/');
|
|
68
|
+
logger.log('');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 提示如何启用插件
|
|
72
|
+
const pluginName = extractPluginName(pluginToInstall, pluginType);
|
|
73
|
+
if (pluginName) {
|
|
74
|
+
logger.log('🔌 启用插件:');
|
|
75
|
+
logger.log(`在 zhin.config.ts 中添加:`);
|
|
76
|
+
logger.log('');
|
|
77
|
+
logger.log(' export default defineConfig({');
|
|
78
|
+
logger.log(' plugins: [');
|
|
79
|
+
logger.log(` '${pluginName}'`);
|
|
80
|
+
logger.log(' ]');
|
|
81
|
+
logger.log(' });');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
} catch (error) {
|
|
85
|
+
logger.error('安装失败');
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
logger.error(`安装插件失败: ${error.message}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// 别名命令
|
|
96
|
+
export const addCommand = new Command('add')
|
|
97
|
+
.description('安装插件(install 的别名)')
|
|
98
|
+
.argument('[plugin]', '插件名称或 git 地址')
|
|
99
|
+
.option('-S, --save', '安装到 dependencies(默认)', true)
|
|
100
|
+
.option('-D, --save-dev', '安装到 devDependencies', false)
|
|
101
|
+
.option('-g, --global', '全局安装', false)
|
|
102
|
+
.action(async (plugin: string, options: InstallOptions) => {
|
|
103
|
+
await installCommand.parseAsync(['node', 'zhin', 'install', plugin || '', ...buildOptionsArray(options)], { from: 'user' });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 检测插件类型
|
|
108
|
+
*/
|
|
109
|
+
function detectPluginType(plugin: string): 'npm' | 'git' | 'github' | 'gitlab' | 'bitbucket' {
|
|
110
|
+
// Git 协议
|
|
111
|
+
if (plugin.startsWith('git://') || plugin.startsWith('git+')) {
|
|
112
|
+
return 'git';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// HTTPS/SSH git 地址
|
|
116
|
+
if (plugin.includes('github.com') || plugin.includes('gitlab.com') || plugin.includes('bitbucket.org')) {
|
|
117
|
+
if (plugin.includes('github.com')) return 'github';
|
|
118
|
+
if (plugin.includes('gitlab.com')) return 'gitlab';
|
|
119
|
+
if (plugin.includes('bitbucket.org')) return 'bitbucket';
|
|
120
|
+
return 'git';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// GitHub 简写 (user/repo)
|
|
124
|
+
if (/^[\w-]+\/[\w-]+$/.test(plugin)) {
|
|
125
|
+
return 'github';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 默认为 npm 包
|
|
129
|
+
return 'npm';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 构建安装命令
|
|
134
|
+
*/
|
|
135
|
+
function buildInstallCommand(plugin: string, type: string, options: InstallOptions): string {
|
|
136
|
+
const parts = ['pnpm', 'add'];
|
|
137
|
+
|
|
138
|
+
// 添加保存选项
|
|
139
|
+
if (options.saveDev) {
|
|
140
|
+
parts.push('-D');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (options.global) {
|
|
144
|
+
parts.push('-g');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 处理不同类型的插件
|
|
148
|
+
let packageSpec = plugin;
|
|
149
|
+
|
|
150
|
+
switch (type) {
|
|
151
|
+
case 'github':
|
|
152
|
+
// 如果是简写形式,转换为完整 GitHub URL
|
|
153
|
+
if (/^[\w-]+\/[\w-]+$/.test(plugin)) {
|
|
154
|
+
packageSpec = `github:${plugin}`;
|
|
155
|
+
} else if (!plugin.startsWith('git+') && !plugin.startsWith('https://')) {
|
|
156
|
+
packageSpec = `git+${plugin}`;
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
case 'gitlab':
|
|
161
|
+
if (!plugin.startsWith('git+') && !plugin.startsWith('https://')) {
|
|
162
|
+
packageSpec = `git+${plugin}`;
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
|
|
166
|
+
case 'bitbucket':
|
|
167
|
+
if (!plugin.startsWith('git+') && !plugin.startsWith('https://')) {
|
|
168
|
+
packageSpec = `git+${plugin}`;
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case 'git':
|
|
173
|
+
// Git URL 直接使用
|
|
174
|
+
break;
|
|
175
|
+
|
|
176
|
+
case 'npm':
|
|
177
|
+
default:
|
|
178
|
+
// npm 包名直接使用
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
parts.push(packageSpec);
|
|
183
|
+
|
|
184
|
+
return parts.join(' ');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 提取插件名称
|
|
189
|
+
*/
|
|
190
|
+
function extractPluginName(plugin: string, type: string): string | null {
|
|
191
|
+
switch (type) {
|
|
192
|
+
case 'npm':
|
|
193
|
+
// npm 包名可能包含 scope 和版本号
|
|
194
|
+
// @scope/package@version -> @scope/package 或 package
|
|
195
|
+
const match = plugin.match(/^(@?[\w-]+\/)?([^@]+)/);
|
|
196
|
+
if (match) {
|
|
197
|
+
const fullName = match[0].replace(/@[\d.]+.*$/, ''); // 移除版本号
|
|
198
|
+
// 如果是 @zhin.js/ 开头的包,提取最后的名称
|
|
199
|
+
if (fullName.startsWith('@zhin.js/')) {
|
|
200
|
+
return fullName.replace('@zhin.js/', '');
|
|
201
|
+
}
|
|
202
|
+
return fullName;
|
|
203
|
+
}
|
|
204
|
+
return plugin;
|
|
205
|
+
|
|
206
|
+
case 'github':
|
|
207
|
+
case 'gitlab':
|
|
208
|
+
case 'bitbucket':
|
|
209
|
+
// 从 git URL 中提取仓库名
|
|
210
|
+
const repoMatch = plugin.match(/\/([^/]+?)(\.git)?$/);
|
|
211
|
+
if (repoMatch) {
|
|
212
|
+
return repoMatch[1];
|
|
213
|
+
}
|
|
214
|
+
// 简写形式 user/repo
|
|
215
|
+
if (/^[\w-]+\/([\w-]+)$/.test(plugin)) {
|
|
216
|
+
return plugin.split('/')[1];
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
|
|
220
|
+
case 'git':
|
|
221
|
+
// 从 git URL 中提取仓库名
|
|
222
|
+
const gitMatch = plugin.match(/\/([^/]+?)(\.git)?$/);
|
|
223
|
+
if (gitMatch) {
|
|
224
|
+
return gitMatch[1];
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
|
|
228
|
+
default:
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* 构建选项数组
|
|
235
|
+
*/
|
|
236
|
+
function buildOptionsArray(options: InstallOptions): string[] {
|
|
237
|
+
const arr: string[] = [];
|
|
238
|
+
if (options.saveDev) arr.push('-D');
|
|
239
|
+
if (options.global) arr.push('-g');
|
|
240
|
+
return arr;
|
|
241
|
+
}
|
|
242
|
+
|