@zhin.js/cli 1.0.4 → 1.0.6

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.
@@ -0,0 +1,339 @@
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 newCommand = new Command('new')
8
+ .description('创建插件包模板')
9
+ .argument('[plugin-name]', '插件名称(如: my-plugin)')
10
+ .option('--skip-install', '跳过依赖安装', false)
11
+ .action(async (pluginName, options) => {
12
+ try {
13
+ let name = pluginName;
14
+ if (!name) {
15
+ const { pluginName: inputName } = await inquirer.prompt([
16
+ {
17
+ type: 'input',
18
+ name: 'pluginName',
19
+ message: '请输入插件名称:',
20
+ default: 'my-plugin',
21
+ validate: (input) => {
22
+ if (!input.trim()) {
23
+ return '插件名称不能为空';
24
+ }
25
+ if (!/^[a-zA-Z0-9-_]+$/.test(input)) {
26
+ return '插件名称只能包含字母、数字、横线和下划线';
27
+ }
28
+ return true;
29
+ }
30
+ }
31
+ ]);
32
+ name = inputName;
33
+ }
34
+ // 确定插件目录
35
+ const pluginDir = path.resolve(process.cwd(), 'plugins', name);
36
+ // 检查目录是否已存在
37
+ if (fs.existsSync(pluginDir)) {
38
+ logger.error(`插件目录已存在: ${pluginDir}`);
39
+ process.exit(1);
40
+ }
41
+ logger.info(`正在创建插件包 ${name}...`);
42
+ // 创建插件包结构
43
+ await createPluginPackage(pluginDir, name, options);
44
+ // 自动添加到 app/package.json
45
+ await addPluginToApp(name);
46
+ logger.success(`✓ 插件包 ${name} 创建成功!`);
47
+ logger.log('');
48
+ logger.log('📝 下一步操作:');
49
+ logger.log(` cd plugins/${name}`);
50
+ if (options.skipInstall) {
51
+ logger.log(` pnpm install`);
52
+ }
53
+ logger.log(` pnpm build`);
54
+ logger.log(` pnpm dev # 开发模式(监听文件变化)`);
55
+ logger.log('');
56
+ logger.log('📦 发布到 npm:');
57
+ logger.log(` pnpm publish`);
58
+ }
59
+ catch (error) {
60
+ logger.error(`创建插件失败: ${error}`);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ async function createPluginPackage(pluginDir, pluginName, options) {
65
+ const capitalizedName = pluginName.charAt(0).toUpperCase() + pluginName.slice(1).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
66
+ const packageName = `@zhin.js/${pluginName}`;
67
+ // 创建目录结构
68
+ await fs.ensureDir(pluginDir);
69
+ await fs.ensureDir(path.join(pluginDir, 'app'));
70
+ await fs.ensureDir(path.join(pluginDir, 'client'));
71
+ await fs.ensureDir(path.join(pluginDir, 'lib'));
72
+ await fs.ensureDir(path.join(pluginDir, 'dist'));
73
+ // 创建 package.json
74
+ const packageJson = {
75
+ name: packageName,
76
+ version: '0.1.0',
77
+ description: `Zhin.js ${capitalizedName} 插件`,
78
+ type: 'module',
79
+ main: './lib/index.js',
80
+ types: './lib/index.d.ts',
81
+ exports: {
82
+ '.': {
83
+ types: './lib/index.d.ts',
84
+ import: './lib/index.js'
85
+ },
86
+ './client': {
87
+ import: './dist/index.js'
88
+ }
89
+ },
90
+ files: [
91
+ 'lib',
92
+ 'app',
93
+ 'dist',
94
+ 'client',
95
+ 'README.md',
96
+ 'CHANGELOG.md'
97
+ ],
98
+ scripts: {
99
+ build: 'pnpm build:app && pnpm build:client',
100
+ 'build:app': 'tsc --project tsconfig.app.json',
101
+ 'build:client': 'tsc --project tsconfig.client.json',
102
+ dev: 'tsc --project tsconfig.app.json --watch',
103
+ clean: 'rm -rf lib dist',
104
+ prepublishOnly: 'pnpm build'
105
+ },
106
+ keywords: [
107
+ 'zhin',
108
+ 'zhin-plugin',
109
+ pluginName
110
+ ],
111
+ author: '',
112
+ license: 'MIT',
113
+ peerDependencies: {
114
+ 'zhin.js': 'workspace:*'
115
+ },
116
+ dependencies: {
117
+ '@zhin.js/client': 'workspace:*'
118
+ },
119
+ devDependencies: {
120
+ '@zhin.js/types': 'workspace:*',
121
+ '@types/node': 'latest',
122
+ '@types/react': 'latest',
123
+ 'typescript': 'latest',
124
+ 'react': 'latest',
125
+ 'react-dom': 'latest',
126
+ 'lucide-react': 'latest'
127
+ }
128
+ };
129
+ await fs.writeJson(path.join(pluginDir, 'package.json'), packageJson, { spaces: 2 });
130
+ // 创建 tsconfig.app.json (插件代码)
131
+ const tsConfigApp = {
132
+ extends: '../../tsconfig.json',
133
+ compilerOptions: {
134
+ rootDir: './app',
135
+ outDir: './lib',
136
+ declaration: true,
137
+ noEmit: false
138
+ },
139
+ include: ['app/**/*'],
140
+ exclude: ['node_modules', 'lib', 'dist']
141
+ };
142
+ await fs.writeJson(path.join(pluginDir, 'tsconfig.app.json'), tsConfigApp, { spaces: 2 });
143
+ // 创建 tsconfig.client.json (客户端代码)
144
+ const tsConfigClient = {
145
+ compilerOptions: {
146
+ target: 'ES2022',
147
+ module: 'ESNext',
148
+ moduleResolution: 'bundler',
149
+ rootDir: './client',
150
+ outDir: './dist',
151
+ declaration: false,
152
+ jsx: 'react-jsx',
153
+ baseUrl: '.',
154
+ skipLibCheck: true,
155
+ esModuleInterop: true,
156
+ allowSyntheticDefaultImports: true
157
+ },
158
+ include: ['client/**/*'],
159
+ exclude: ['node_modules', 'lib', 'dist']
160
+ };
161
+ await fs.writeJson(path.join(pluginDir, 'tsconfig.client.json'), tsConfigClient, { spaces: 2 });
162
+ // 创建 tsconfig.json (编辑器支持)
163
+ const tsConfig = {
164
+ extends: '../../tsconfig.json',
165
+ include: ['app/**/*', 'client/**/*'],
166
+ exclude: ['node_modules', 'lib', 'dist']
167
+ };
168
+ await fs.writeJson(path.join(pluginDir, 'tsconfig.json'), tsConfig, { spaces: 2 });
169
+ // 创建插件主入口文件 app/index.ts
170
+ const appContent = `import {
171
+ useLogger,
172
+ useContext,
173
+ onDispose,
174
+ } from 'zhin.js';
175
+ import path from 'node:path';
176
+
177
+ const logger = useLogger();
178
+
179
+ // 注册客户端入口(如果有客户端代码)
180
+ useContext('web', (web) => {
181
+ const dispose = web.addEntry(
182
+ path.resolve(import.meta.dirname, '../client/index.tsx')
183
+ );
184
+ return dispose;
185
+ });
186
+
187
+ // 插件销毁时的清理
188
+ onDispose(() => {
189
+ logger.info('${capitalizedName} 插件已销毁');
190
+ });
191
+
192
+ logger.info('${capitalizedName} 插件已加载');
193
+ `;
194
+ await fs.writeFile(path.join(pluginDir, 'app', 'index.ts'), appContent);
195
+ // 创建客户端入口文件 client/index.tsx
196
+ const clientContent = `import { addPage } from '@zhin.js/client';
197
+ import { Component } from 'lucide-react';
198
+ import ${capitalizedName}Page from './pages/${capitalizedName}Page';
199
+
200
+ addPage({
201
+ key: '${pluginName}-page',
202
+ path: '/plugins/${pluginName}',
203
+ title: '${capitalizedName}',
204
+ icon: <Component className="w-5 h-5" />,
205
+ element: <${capitalizedName}Page />
206
+ });
207
+
208
+ export { ${capitalizedName}Page };
209
+ `;
210
+ await fs.writeFile(path.join(pluginDir, 'client', 'index.tsx'), clientContent);
211
+ // 创建客户端页面组件
212
+ await fs.ensureDir(path.join(pluginDir, 'client', 'pages'));
213
+ const pageContent = `import { useEffect } from 'react';
214
+
215
+ export default function ${capitalizedName}Page() {
216
+
217
+ useEffect(() => {
218
+ console.log('${capitalizedName} 页面已挂载');
219
+ }, []);
220
+
221
+ return (
222
+ <div className="p-6">
223
+ <h1 className="text-2xl font-bold mb-4">${capitalizedName}</h1>
224
+ </div>
225
+ );
226
+ }
227
+ `;
228
+ await fs.writeFile(path.join(pluginDir, 'client', 'pages', `${capitalizedName}Page.tsx`), pageContent);
229
+ // 创建 README.md
230
+ const readmeContent = `# ${packageName}
231
+
232
+ ${capitalizedName} 插件 for Zhin.js
233
+
234
+ ## 安装
235
+
236
+ \`\`\`bash
237
+ pnpm add ${packageName}
238
+ \`\`\`
239
+
240
+ ## 使用
241
+
242
+ 在 \`zhin.config.ts\` 中添加插件:
243
+
244
+ \`\`\`typescript
245
+ export default defineConfig({
246
+ plugins: [
247
+ '${pluginName}'
248
+ ]
249
+ });
250
+ \`\`\`
251
+
252
+ ## 开发
253
+
254
+ \`\`\`bash
255
+ # 安装依赖
256
+ pnpm install
257
+
258
+ # 构建
259
+ pnpm build
260
+
261
+ # 开发模式
262
+ pnpm dev
263
+ \`\`\`
264
+
265
+ ## 许可证
266
+
267
+ MIT
268
+ `;
269
+ await fs.writeFile(path.join(pluginDir, 'README.md'), readmeContent);
270
+ // 创建 CHANGELOG.md
271
+ const changelogContent = `# ${packageName}
272
+
273
+ ## 0.1.0
274
+
275
+ ### Features
276
+
277
+ - 初始版本
278
+ `;
279
+ await fs.writeFile(path.join(pluginDir, 'CHANGELOG.md'), changelogContent);
280
+ // 创建 .gitignore
281
+ const gitignoreContent = `node_modules/
282
+ lib/
283
+ dist/
284
+ *.log
285
+ .DS_Store
286
+ `;
287
+ await fs.writeFile(path.join(pluginDir, '.gitignore'), gitignoreContent);
288
+ // 安装依赖
289
+ if (!options.skipInstall) {
290
+ logger.info('正在安装依赖...');
291
+ try {
292
+ execSync('pnpm install', {
293
+ cwd: pluginDir,
294
+ stdio: 'inherit'
295
+ });
296
+ logger.success('✓ 依赖安装成功');
297
+ }
298
+ catch (error) {
299
+ logger.warn('⚠ 依赖安装失败,请手动执行 pnpm install');
300
+ }
301
+ }
302
+ }
303
+ async function addPluginToApp(pluginName) {
304
+ try {
305
+ const rootPackageJsonPath = path.resolve(process.cwd(), 'package.json');
306
+ // 检查根 package.json 是否存在
307
+ if (!fs.existsSync(rootPackageJsonPath)) {
308
+ logger.warn('⚠ 未找到根目录 package.json,跳过依赖添加');
309
+ return;
310
+ }
311
+ const packageJson = await fs.readJson(rootPackageJsonPath);
312
+ const packageName = `@zhin.js/${pluginName}`;
313
+ // 初始化 dependencies
314
+ if (!packageJson.dependencies) {
315
+ packageJson.dependencies = {};
316
+ }
317
+ // 添加 workspace 依赖
318
+ packageJson.dependencies[packageName] = 'workspace:*';
319
+ // 写回文件
320
+ await fs.writeJson(rootPackageJsonPath, packageJson, { spaces: 2 });
321
+ logger.success(`✓ 已将 ${packageName} 添加到 package.json`);
322
+ // 重新安装依赖
323
+ logger.info('正在更新依赖...');
324
+ try {
325
+ execSync('pnpm install', {
326
+ cwd: process.cwd(),
327
+ stdio: 'inherit'
328
+ });
329
+ logger.success('✓ 依赖更新成功');
330
+ }
331
+ catch (error) {
332
+ logger.warn('⚠ 依赖更新失败,请手动执行 pnpm install');
333
+ }
334
+ }
335
+ catch (error) {
336
+ logger.warn(`⚠ 添加到 package.json 失败: ${error}`);
337
+ }
338
+ }
339
+ //# sourceMappingURL=new.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Zhin机器人框架CLI工具",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -15,20 +15,20 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "commander": "^11.1.0",
18
- "inquirer": "^9.2.12",
19
18
  "chalk": "^5.3.0",
20
19
  "ora": "^7.0.1",
21
20
  "fs-extra": "^11.1.1",
22
21
  "cross-spawn": "^7.0.3",
23
22
  "dotenv": "^16.3.1",
24
23
  "glob": "^10.3.10",
24
+ "inquirer": "^9.2.12",
25
25
  "@zhin.js/logger": "0.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/fs-extra": "^11.0.4",
29
29
  "@types/cross-spawn": "^6.0.6",
30
- "@types/inquirer": "^9.0.7",
31
30
  "@types/node": "^20.0.0",
31
+ "@types/inquirer": "^9.0.7",
32
32
  "typescript": "^5.3.0"
33
33
  },
34
34
  "scripts": {
package/src/cli.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
- import { initCommand } from './commands/init.js';
5
4
  import { startCommand, restartCommand } from './commands/start.js';
6
5
  import { stopCommand } from './commands/stop.js';
7
6
  import { devCommand } from './commands/dev.js';
8
7
  import { buildCommand } from './commands/build.js';
8
+ import { newCommand } from './commands/new.js';
9
9
 
10
10
  const program = new Command();
11
11
 
@@ -15,11 +15,11 @@ program
15
15
  .version('1.0.1');
16
16
 
17
17
  // 注册命令
18
- program.addCommand(initCommand);
19
18
  program.addCommand(startCommand);
20
19
  program.addCommand(restartCommand);
21
20
  program.addCommand(stopCommand);
22
21
  program.addCommand(devCommand);
23
22
  program.addCommand(buildCommand);
23
+ program.addCommand(newCommand);
24
24
 
25
25
  program.parse();
@@ -5,48 +5,57 @@ import fs from 'fs-extra';
5
5
  import path from 'path';
6
6
 
7
7
  export const buildCommand = new Command('build')
8
- .description('构建机器人项目')
8
+ .description('构建插件项目')
9
+ .argument('[plugin]', '插件名称(默认构建所有插件)')
9
10
  .option('--clean', '清理输出目录', false)
10
- .action(async (options: { clean: boolean }) => {
11
+ .action(async (pluginName: string | undefined, options: { clean: boolean }) => {
11
12
  try {
12
13
  const cwd = process.cwd();
13
14
 
14
- // 检查是否是Zhin项目
15
- if (!isZhinProject(cwd)) {
16
- logger.error('当前目录不是Zhin项目');
15
+ // 检查是否是 workspace 项目
16
+ if (!isWorkspaceProject(cwd)) {
17
+ logger.error('当前目录不是 Zhin workspace 项目');
17
18
  process.exit(1);
18
19
  }
19
20
 
20
- const distPath = path.join(cwd, 'dist');
21
+ const pluginsDir = path.join(cwd, 'plugins');
21
22
 
22
- // 清理输出目录
23
- if (options.clean && fs.existsSync(distPath)) {
24
- logger.info('正在清理输出目录...');
25
- await fs.remove(distPath);
23
+ if (!fs.existsSync(pluginsDir)) {
24
+ logger.error('未找到 plugins 目录');
25
+ process.exit(1);
26
26
  }
27
27
 
28
- logger.info('正在构建项目...');
29
-
30
- // 使用TypeScript编译
31
- const child = spawn('npx', ['tsc','--project','tsconfig.json'], {
32
- cwd,
33
- stdio: 'inherit',
34
- shell:true,
35
- });
36
-
37
- child.on('close', (code) => {
38
- if (code === 0) {
39
- logger.info('构建完成!');
40
- } else {
41
- logger.error(`构建失败,退出码: ${code}`);
28
+ // 如果指定了插件名称
29
+ if (pluginName) {
30
+ const pluginPath = path.join(pluginsDir, pluginName);
31
+
32
+ if (!fs.existsSync(pluginPath)) {
33
+ logger.error(`未找到插件: ${pluginName}`);
42
34
  process.exit(1);
43
35
  }
44
- });
45
-
46
- child.on('error', (error) => {
47
- logger.error(`构建失败: ${error.message}`);
48
- process.exit(1);
49
- });
36
+
37
+ await buildPlugin(pluginPath, pluginName, options.clean);
38
+ } else {
39
+ // 构建所有插件
40
+ const plugins = await fs.readdir(pluginsDir);
41
+ const validPlugins = plugins.filter(p => {
42
+ const pluginPath = path.join(pluginsDir, p);
43
+ const stat = fs.statSync(pluginPath);
44
+ return stat.isDirectory() && fs.existsSync(path.join(pluginPath, 'package.json'));
45
+ });
46
+
47
+ if (validPlugins.length === 0) {
48
+ logger.warn('未找到任何插件');
49
+ return;
50
+ }
51
+
52
+ logger.info(`找到 ${validPlugins.length} 个插件,开始构建...`);
53
+
54
+ for (const plugin of validPlugins) {
55
+ const pluginPath = path.join(pluginsDir, plugin);
56
+ await buildPlugin(pluginPath, plugin, options.clean);
57
+ }
58
+ }
50
59
 
51
60
  } catch (error) {
52
61
  logger.error(`构建失败: ${error}`);
@@ -54,9 +63,55 @@ export const buildCommand = new Command('build')
54
63
  }
55
64
  });
56
65
 
57
- function isZhinProject(cwd: string): boolean {
66
+ async function buildPlugin(pluginPath: string, pluginName: string, clean: boolean): Promise<void> {
67
+ return new Promise((resolve, reject) => {
68
+ logger.info(`正在构建插件: ${pluginName}...`);
69
+
70
+ // 清理输出目录
71
+ if (clean) {
72
+ const libPath = path.join(pluginPath, 'lib');
73
+ const distPath = path.join(pluginPath, 'dist');
74
+
75
+ if (fs.existsSync(libPath)) {
76
+ fs.removeSync(libPath);
77
+ logger.info(`✓ 已清理 ${pluginName}/lib`);
78
+ }
79
+
80
+ if (fs.existsSync(distPath)) {
81
+ fs.removeSync(distPath);
82
+ logger.info(`✓ 已清理 ${pluginName}/dist`);
83
+ }
84
+ }
85
+
86
+ // 使用 pnpm build 构建插件
87
+ const child = spawn('pnpm', ['build'], {
88
+ cwd: pluginPath,
89
+ stdio: 'inherit',
90
+ shell: true,
91
+ });
92
+
93
+ child.on('close', (code) => {
94
+ if (code === 0) {
95
+ logger.success(`✓ ${pluginName} 构建完成`);
96
+ resolve();
97
+ } else {
98
+ logger.error(`✗ ${pluginName} 构建失败,退出码: ${code}`);
99
+ reject(new Error(`Build failed with code ${code}`));
100
+ }
101
+ });
102
+
103
+ child.on('error', (error) => {
104
+ logger.error(`✗ ${pluginName} 构建失败: ${error.message}`);
105
+ reject(error);
106
+ });
107
+ });
108
+ }
109
+
110
+ function isWorkspaceProject(cwd: string): boolean {
111
+ const workspaceYamlPath = path.join(cwd, 'pnpm-workspace.yaml');
58
112
  const packageJsonPath = path.join(cwd, 'package.json');
59
- if (!fs.existsSync(packageJsonPath)) {
113
+
114
+ if (!fs.existsSync(workspaceYamlPath) || !fs.existsSync(packageJsonPath)) {
60
115
  return false;
61
116
  }
62
117