@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.
- package/CHANGELOG.md +12 -0
- package/README.md +125 -57
- package/lib/cli.js +2 -2
- package/lib/cli.js.map +1 -1
- package/lib/commands/build.d.ts.map +1 -1
- package/lib/commands/build.js +72 -26
- package/lib/commands/build.js.map +1 -1
- package/lib/commands/new.d.ts +3 -0
- package/lib/commands/new.d.ts.map +1 -0
- package/lib/commands/new.js +339 -0
- package/lib/commands/new.js.map +1 -0
- package/package.json +3 -3
- package/src/cli.ts +2 -2
- package/src/commands/build.ts +87 -32
- package/src/commands/new.ts +378 -0
- package/lib/commands/init.d.ts +0 -3
- package/lib/commands/init.d.ts.map +0 -1
- package/lib/commands/init.js +0 -845
- package/lib/commands/init.js.map +0 -1
- package/src/commands/init.ts +0 -893
package/lib/commands/init.js
DELETED
|
@@ -1,845 +0,0 @@
|
|
|
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
|
-
export const initCommand = new Command('init')
|
|
7
|
-
.description('初始化新的Zhin机器人项目')
|
|
8
|
-
.argument('[project-name]', '项目名称')
|
|
9
|
-
.option('-c, --config <format>', '配置文件格式 (json|yaml|toml|ts|js)', 'js')
|
|
10
|
-
.option('-p, --package-manager <manager>', '包管理器 (npm|yarn|pnpm)', 'pnpm')
|
|
11
|
-
.option('-r, --runtime <runtime>', '运行时 (node|bun)', 'node')
|
|
12
|
-
.option('-y, --yes', '自动回答所有问题')
|
|
13
|
-
.action(async (projectName, options) => {
|
|
14
|
-
if (options.yes) {
|
|
15
|
-
options.config = 'js';
|
|
16
|
-
options.packageManager = 'pnpm';
|
|
17
|
-
options.runtime = 'node';
|
|
18
|
-
}
|
|
19
|
-
try {
|
|
20
|
-
let name = projectName;
|
|
21
|
-
if (!name) {
|
|
22
|
-
const { projectName: inputName } = await inquirer.prompt([
|
|
23
|
-
{
|
|
24
|
-
type: 'input',
|
|
25
|
-
name: 'projectName',
|
|
26
|
-
message: '请输入项目名称:',
|
|
27
|
-
default: 'my-zhin-bot',
|
|
28
|
-
validate: (input) => {
|
|
29
|
-
if (!input.trim()) {
|
|
30
|
-
return '项目名称不能为空';
|
|
31
|
-
}
|
|
32
|
-
if (!/^[a-zA-Z0-9-_]+$/.test(input)) {
|
|
33
|
-
return '项目名称只能包含字母、数字、横线和下划线';
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
]);
|
|
39
|
-
name = inputName;
|
|
40
|
-
}
|
|
41
|
-
if (!options.runtime) {
|
|
42
|
-
const { runtime: inputRuntime } = await inquirer.prompt([
|
|
43
|
-
{
|
|
44
|
-
type: 'list',
|
|
45
|
-
name: 'runtime',
|
|
46
|
-
message: '选择运行时:',
|
|
47
|
-
choices: [
|
|
48
|
-
{ name: 'Node.js (推荐)', value: 'node' },
|
|
49
|
-
{ name: 'Bun', value: 'bun' }
|
|
50
|
-
],
|
|
51
|
-
default: options.runtime || 'node'
|
|
52
|
-
},
|
|
53
|
-
]);
|
|
54
|
-
options.runtime = inputRuntime;
|
|
55
|
-
}
|
|
56
|
-
if (!options.packageManager) {
|
|
57
|
-
const { packageManager: inputPackageManager } = await inquirer.prompt([
|
|
58
|
-
{
|
|
59
|
-
type: 'list',
|
|
60
|
-
name: 'packageManager',
|
|
61
|
-
message: '选择包管理器:',
|
|
62
|
-
choices: [
|
|
63
|
-
{ name: 'pnpm (推荐)', value: 'pnpm' },
|
|
64
|
-
{ name: 'npm', value: 'npm' },
|
|
65
|
-
{ name: 'yarn', value: 'yarn' }
|
|
66
|
-
],
|
|
67
|
-
default: options.packageManager || 'pnpm'
|
|
68
|
-
}
|
|
69
|
-
]);
|
|
70
|
-
options.packageManager = inputPackageManager;
|
|
71
|
-
}
|
|
72
|
-
if (!options.config) {
|
|
73
|
-
const { configFormat: inputConfigFormat } = await inquirer.prompt([
|
|
74
|
-
{
|
|
75
|
-
type: 'list',
|
|
76
|
-
name: 'configFormat',
|
|
77
|
-
message: '选择配置文件格式:',
|
|
78
|
-
choices: [
|
|
79
|
-
{ name: 'JavaScript (推荐)', value: 'js' },
|
|
80
|
-
{ name: 'TypeScript', value: 'ts' },
|
|
81
|
-
{ name: 'YAML', value: 'yaml' },
|
|
82
|
-
{ name: 'JSON', value: 'json' },
|
|
83
|
-
{ name: 'TOML', value: 'toml' }
|
|
84
|
-
],
|
|
85
|
-
default: options.config || 'js'
|
|
86
|
-
}
|
|
87
|
-
]);
|
|
88
|
-
options.config = inputConfigFormat;
|
|
89
|
-
}
|
|
90
|
-
const projectPath = path.resolve(process.cwd(), name);
|
|
91
|
-
const realName = path.basename(projectPath);
|
|
92
|
-
// 检查目录是否已存在
|
|
93
|
-
if (fs.existsSync(projectPath)) {
|
|
94
|
-
logger.error(`目录 ${realName} 已存在`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
logger.info(`正在创建项目 ${realName}...`);
|
|
98
|
-
// 创建项目目录结构
|
|
99
|
-
await createProjectStructure(projectPath, realName, options);
|
|
100
|
-
logger.success(`项目 ${realName} 创建成功!`);
|
|
101
|
-
logger.log('');
|
|
102
|
-
logger.log('🎉 下一步操作:');
|
|
103
|
-
logger.log(` cd ${realName}`);
|
|
104
|
-
const installCommand = getInstallCommand(options.packageManager);
|
|
105
|
-
logger.log(` ${installCommand} # 安装依赖`);
|
|
106
|
-
logger.log(` npm run dev # 开发环境启动`);
|
|
107
|
-
logger.log(` npm run build # 构建项目`);
|
|
108
|
-
logger.log(` npm run start # 生产环境前台启动`);
|
|
109
|
-
logger.log(` npm run daemon # 生产环境后台启动`);
|
|
110
|
-
logger.log(` npm run stop # 停止机器人`);
|
|
111
|
-
logger.log('');
|
|
112
|
-
logger.log('📚 相关文档:');
|
|
113
|
-
logger.log(' https://github.com/zhinjs/zhin - 项目主页');
|
|
114
|
-
logger.log(' https://zhinjs.github.io - 官方文档');
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
logger.error(`创建项目失败: ${error}`);
|
|
118
|
-
process.exit(1);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
function getInstallCommand(packageManager) {
|
|
122
|
-
switch (packageManager) {
|
|
123
|
-
case 'yarn': return 'yarn install';
|
|
124
|
-
case 'pnpm': return 'pnpm install';
|
|
125
|
-
default: return 'npm install';
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
async function createProjectStructure(projectPath, projectName, options) {
|
|
129
|
-
// 创建目录结构
|
|
130
|
-
await fs.ensureDir(projectPath);
|
|
131
|
-
await fs.ensureDir(path.join(projectPath, 'src'));
|
|
132
|
-
await fs.ensureDir(path.join(projectPath, 'src', 'plugins'));
|
|
133
|
-
await fs.ensureDir(path.join(projectPath, 'dist'));
|
|
134
|
-
await fs.ensureDir(path.join(projectPath, 'data'));
|
|
135
|
-
// 检查是否在工作区中
|
|
136
|
-
const isInWorkspace = await checkIfInWorkspace();
|
|
137
|
-
const versionSuffix = isInWorkspace ? 'workspace:*' : 'latest';
|
|
138
|
-
// 创建 package.json
|
|
139
|
-
const packageJson = {
|
|
140
|
-
name: projectName,
|
|
141
|
-
private: true,
|
|
142
|
-
version: '0.1.0',
|
|
143
|
-
description: `${projectName} 机器人`,
|
|
144
|
-
type: 'module',
|
|
145
|
-
main: 'src/index.ts',
|
|
146
|
-
scripts: {
|
|
147
|
-
dev: 'zhin dev',
|
|
148
|
-
start: options.runtime === 'bun' ? 'zhin start --bun' : 'zhin start',
|
|
149
|
-
daemon: options.runtime === 'bun' ? 'zhin start --bun --daemon' : 'zhin start --daemon',
|
|
150
|
-
build: 'zhin build',
|
|
151
|
-
stop: 'zhin stop'
|
|
152
|
-
},
|
|
153
|
-
dependencies: {
|
|
154
|
-
'zhin.js': versionSuffix,
|
|
155
|
-
'@zhin.js/adapter-process': versionSuffix,
|
|
156
|
-
'@zhin.js/http': versionSuffix,
|
|
157
|
-
'@zhin.js/client': versionSuffix,
|
|
158
|
-
'@zhin.js/console': versionSuffix
|
|
159
|
-
},
|
|
160
|
-
devDependencies: {
|
|
161
|
-
'@zhin.js/cli': versionSuffix,
|
|
162
|
-
'@zhin.js/types': versionSuffix,
|
|
163
|
-
"react": "latest",
|
|
164
|
-
"react-dom": "latest",
|
|
165
|
-
"@types/node": "latest",
|
|
166
|
-
'typescript': 'latest',
|
|
167
|
-
...(options.runtime === 'bun' ? {
|
|
168
|
-
'bun': 'latest'
|
|
169
|
-
} : {
|
|
170
|
-
'tsx': 'latest'
|
|
171
|
-
})
|
|
172
|
-
},
|
|
173
|
-
engines: {
|
|
174
|
-
node: '>=18.0.0'
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
await fs.writeJson(path.join(projectPath, 'package.json'), packageJson, { spaces: 2 });
|
|
178
|
-
// 创建 tsconfig.json
|
|
179
|
-
const tsConfig = {
|
|
180
|
-
compilerOptions: {
|
|
181
|
-
target: 'ES2022',
|
|
182
|
-
module: 'ESNext',
|
|
183
|
-
moduleResolution: 'bundler',
|
|
184
|
-
outDir: './dist',
|
|
185
|
-
strict: true,
|
|
186
|
-
esModuleInterop: true,
|
|
187
|
-
skipLibCheck: true,
|
|
188
|
-
forceConsistentCasingInFileNames: true,
|
|
189
|
-
resolveJsonModule: true,
|
|
190
|
-
isolatedModules: true,
|
|
191
|
-
allowSyntheticDefaultImports: true,
|
|
192
|
-
experimentalDecorators: true,
|
|
193
|
-
emitDecoratorMetadata: true,
|
|
194
|
-
declaration: false,
|
|
195
|
-
sourceMap: true,
|
|
196
|
-
baseUrl: './src',
|
|
197
|
-
jsx: 'react-jsx',
|
|
198
|
-
jsxImportSource: 'zhin.js',
|
|
199
|
-
types: [
|
|
200
|
-
'@types/node',
|
|
201
|
-
'@zhin.js/types',
|
|
202
|
-
'zhin.js'
|
|
203
|
-
]
|
|
204
|
-
},
|
|
205
|
-
include: ['src/**/*'],
|
|
206
|
-
exclude: ['dist', 'node_modules']
|
|
207
|
-
};
|
|
208
|
-
await fs.writeJson(path.join(projectPath, 'tsconfig.json'), tsConfig, { spaces: 2 });
|
|
209
|
-
// 创建配置文件
|
|
210
|
-
await createConfigFile(projectPath, options.config);
|
|
211
|
-
// 创建主入口文件
|
|
212
|
-
const indexContent = `import { createApp } from 'zhin.js';
|
|
213
|
-
|
|
214
|
-
// 启动机器人
|
|
215
|
-
async function main() {
|
|
216
|
-
try {
|
|
217
|
-
// 异步创建机器人实例 (自动从配置文件加载)
|
|
218
|
-
const app = await createApp();
|
|
219
|
-
await app.start();
|
|
220
|
-
|
|
221
|
-
// 优雅退出处理
|
|
222
|
-
const shutdown = async (signal: string) => {
|
|
223
|
-
await app.stop();
|
|
224
|
-
process.exit(0);
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
228
|
-
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
229
|
-
} catch (error) {
|
|
230
|
-
// console.error 已替换为注释
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// 启动应用
|
|
236
|
-
main().catch(console.error);
|
|
237
|
-
`;
|
|
238
|
-
await fs.writeFile(path.join(projectPath, 'src', 'index.ts'), indexContent);
|
|
239
|
-
// 创建示例插件
|
|
240
|
-
const pluginContent = `import {
|
|
241
|
-
useLogger,
|
|
242
|
-
onMessage,
|
|
243
|
-
addCommand,
|
|
244
|
-
addMiddleware,
|
|
245
|
-
MessageCommand,
|
|
246
|
-
useContext,
|
|
247
|
-
onDispose,
|
|
248
|
-
} from 'zhin.js';
|
|
249
|
-
|
|
250
|
-
const logger = useLogger();
|
|
251
|
-
|
|
252
|
-
// 添加命令
|
|
253
|
-
addCommand(new MessageCommand('hello')
|
|
254
|
-
.action(async (message) => {
|
|
255
|
-
logger.info('Hello command called by:', message.sender.name);
|
|
256
|
-
return '你好!欢迎使用 Zhin 机器人框架!';
|
|
257
|
-
})
|
|
258
|
-
);
|
|
259
|
-
|
|
260
|
-
addCommand(new MessageCommand('status')
|
|
261
|
-
.action(() => {
|
|
262
|
-
const uptime = process.uptime() * 1000;
|
|
263
|
-
const memory = process.memoryUsage();
|
|
264
|
-
return [
|
|
265
|
-
'🤖 机器人状态',
|
|
266
|
-
\`⏱️ 运行时间: \${formatTime(uptime)}\`,
|
|
267
|
-
\`📊 内存使用: \${(memory.rss / 1024 / 1024).toFixed(2)}MB\`,
|
|
268
|
-
\`🔧 Node.js: \${process.version}\`
|
|
269
|
-
].join('\\n');
|
|
270
|
-
})
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
// 添加中间件
|
|
274
|
-
addMiddleware(async (message, next) => {
|
|
275
|
-
logger.info(\`收到消息: \${message.raw}\`);
|
|
276
|
-
await next();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
// 监听消息
|
|
280
|
-
onMessage(async (message) => {
|
|
281
|
-
if (message.raw.includes('帮助')) {
|
|
282
|
-
await message.reply('可用命令:hello, status\\n输入命令即可使用!');
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// 使用 process 上下文
|
|
287
|
-
useContext('process', () => {
|
|
288
|
-
logger.info('Process 适配器已就绪,可以在控制台输入消息进行测试');
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
// 插件销毁时的清理
|
|
292
|
-
onDispose(() => {
|
|
293
|
-
logger.info('测试插件已销毁');
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// 工具函数
|
|
297
|
-
function formatTime(ms: number): string {
|
|
298
|
-
const seconds = Math.floor(ms / 1000);
|
|
299
|
-
const minutes = Math.floor(seconds / 60);
|
|
300
|
-
const hours = Math.floor(minutes / 60);
|
|
301
|
-
const days = Math.floor(hours / 24);
|
|
302
|
-
|
|
303
|
-
if (days > 0) return \`\${days}天 \${hours % 24}小时\`;
|
|
304
|
-
if (hours > 0) return \`\${hours}小时 \${minutes % 60}分钟\`;
|
|
305
|
-
if (minutes > 0) return \`\${minutes}分钟 \${seconds % 60}秒\`;
|
|
306
|
-
return \`\${seconds}秒\`;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
logger.info('测试插件已加载');
|
|
310
|
-
`;
|
|
311
|
-
await fs.writeFile(path.join(projectPath, 'src', 'plugins', 'test-plugin.ts'), pluginContent);
|
|
312
|
-
// 创建 .gitignore
|
|
313
|
-
const gitignoreContent = `# Dependencies
|
|
314
|
-
node_modules/
|
|
315
|
-
|
|
316
|
-
# Production builds
|
|
317
|
-
dist/
|
|
318
|
-
|
|
319
|
-
# Environment variables
|
|
320
|
-
.env
|
|
321
|
-
.env.local
|
|
322
|
-
.env.development
|
|
323
|
-
.env.production
|
|
324
|
-
|
|
325
|
-
# IDE
|
|
326
|
-
.vscode/
|
|
327
|
-
.idea/
|
|
328
|
-
|
|
329
|
-
# OS
|
|
330
|
-
.DS_Store
|
|
331
|
-
Thumbs.db
|
|
332
|
-
|
|
333
|
-
# Logs
|
|
334
|
-
*.log
|
|
335
|
-
npm-debug.log*
|
|
336
|
-
yarn-debug.log*
|
|
337
|
-
yarn-error.log*
|
|
338
|
-
pnpm-debug.log*
|
|
339
|
-
|
|
340
|
-
# PID files
|
|
341
|
-
.zhin.pid
|
|
342
|
-
.zhin-dev.pid
|
|
343
|
-
|
|
344
|
-
# Runtime data
|
|
345
|
-
pids
|
|
346
|
-
*.pid
|
|
347
|
-
*.seed
|
|
348
|
-
*.pid.lock
|
|
349
|
-
|
|
350
|
-
# Coverage directory used by tools like istanbul
|
|
351
|
-
coverage/
|
|
352
|
-
*.lcov
|
|
353
|
-
|
|
354
|
-
# nyc test coverage
|
|
355
|
-
.nyc_output
|
|
356
|
-
|
|
357
|
-
# Dependency directories
|
|
358
|
-
jspm_packages/
|
|
359
|
-
|
|
360
|
-
# Optional npm cache directory
|
|
361
|
-
.npm
|
|
362
|
-
|
|
363
|
-
# Optional eslint cache
|
|
364
|
-
.eslintcache
|
|
365
|
-
|
|
366
|
-
# Microbundle cache
|
|
367
|
-
.rpt2_cache/
|
|
368
|
-
.rts2_cache_cjs/
|
|
369
|
-
.rts2_cache_es/
|
|
370
|
-
.rts2_cache_umd/
|
|
371
|
-
|
|
372
|
-
# Optional REPL history
|
|
373
|
-
.node_repl_history
|
|
374
|
-
|
|
375
|
-
# Output of 'npm pack'
|
|
376
|
-
*.tgz
|
|
377
|
-
|
|
378
|
-
# Yarn Integrity file
|
|
379
|
-
.yarn-integrity
|
|
380
|
-
|
|
381
|
-
# parcel-bundler cache (https://parceljs.org/)
|
|
382
|
-
.cache
|
|
383
|
-
.parcel-cache
|
|
384
|
-
|
|
385
|
-
# Next.js build output
|
|
386
|
-
.next
|
|
387
|
-
|
|
388
|
-
# Nuxt.js build / generate output
|
|
389
|
-
.nuxt
|
|
390
|
-
dist
|
|
391
|
-
|
|
392
|
-
# Gatsby files
|
|
393
|
-
.cache/
|
|
394
|
-
public
|
|
395
|
-
|
|
396
|
-
# Storybook build outputs
|
|
397
|
-
.out
|
|
398
|
-
.storybook-out
|
|
399
|
-
|
|
400
|
-
# Temporary folders
|
|
401
|
-
tmp/
|
|
402
|
-
temp/
|
|
403
|
-
`;
|
|
404
|
-
await fs.writeFile(path.join(projectPath, '.gitignore'), gitignoreContent);
|
|
405
|
-
// 创建 README.md
|
|
406
|
-
const readmeContent = `# ${projectName}
|
|
407
|
-
|
|
408
|
-
使用 Zhin 框架创建的机器人项目。
|
|
409
|
-
|
|
410
|
-
## 🚀 快速开始
|
|
411
|
-
|
|
412
|
-
### 安装依赖
|
|
413
|
-
|
|
414
|
-
\`\`\`bash
|
|
415
|
-
${getInstallCommand(options.packageManager)}
|
|
416
|
-
\`\`\`
|
|
417
|
-
|
|
418
|
-
### 开发环境
|
|
419
|
-
|
|
420
|
-
\`\`\`bash
|
|
421
|
-
npm run dev
|
|
422
|
-
\`\`\`
|
|
423
|
-
|
|
424
|
-
### 生产环境
|
|
425
|
-
|
|
426
|
-
\`\`\`bash
|
|
427
|
-
# 构建项目
|
|
428
|
-
npm run build
|
|
429
|
-
|
|
430
|
-
# 前台启动
|
|
431
|
-
npm run start
|
|
432
|
-
|
|
433
|
-
# 后台启动
|
|
434
|
-
npm run daemon
|
|
435
|
-
\`\`\`
|
|
436
|
-
|
|
437
|
-
### 停止机器人
|
|
438
|
-
|
|
439
|
-
\`\`\`bash
|
|
440
|
-
npm run stop
|
|
441
|
-
\`\`\`
|
|
442
|
-
|
|
443
|
-
## 📁 项目结构
|
|
444
|
-
|
|
445
|
-
\`\`\`
|
|
446
|
-
${projectName}/
|
|
447
|
-
├── src/
|
|
448
|
-
│ ├── index.ts # 主入口文件
|
|
449
|
-
│ └── plugins/ # 插件目录
|
|
450
|
-
│ └── test-plugin.ts # 示例插件
|
|
451
|
-
├── dist/ # 构建输出目录
|
|
452
|
-
├── data/ # 数据目录
|
|
453
|
-
├── zhin.config.${options.config} # 配置文件
|
|
454
|
-
├── package.json # 项目配置
|
|
455
|
-
└── tsconfig.json # TypeScript配置
|
|
456
|
-
\`\`\`
|
|
457
|
-
|
|
458
|
-
## ⚙️ 配置
|
|
459
|
-
|
|
460
|
-
### 机器人配置
|
|
461
|
-
|
|
462
|
-
编辑 \`zhin.config.${options.config}\` 来配置你的机器人:
|
|
463
|
-
|
|
464
|
-
${getConfigExample(options.config)}
|
|
465
|
-
|
|
466
|
-
## 🔌 插件开发
|
|
467
|
-
|
|
468
|
-
在 \`src/plugins/\` 目录下创建你的插件文件。参考 \`test-plugin.ts\` 了解插件开发方式。
|
|
469
|
-
|
|
470
|
-
### 插件示例
|
|
471
|
-
|
|
472
|
-
\`\`\`typescript
|
|
473
|
-
import { usePlugin, useLogger, addCommand } from '@zhin.js/core';
|
|
474
|
-
|
|
475
|
-
const plugin = usePlugin();
|
|
476
|
-
const logger = useLogger();
|
|
477
|
-
|
|
478
|
-
// 添加命令
|
|
479
|
-
addCommand('hello', (message, args) => {
|
|
480
|
-
logger.info('Hello command called:', args);
|
|
481
|
-
});
|
|
482
|
-
\`\`\`
|
|
483
|
-
|
|
484
|
-
## 📚 相关链接
|
|
485
|
-
|
|
486
|
-
- [Zhin 官方文档](https://zhinjs.github.io)
|
|
487
|
-
- [插件开发指南](https://zhinjs.github.io/plugins)
|
|
488
|
-
- [GitHub 仓库](https://github.com/zhinjs/zhin)
|
|
489
|
-
|
|
490
|
-
## 🤝 贡献
|
|
491
|
-
|
|
492
|
-
欢迎提交 Issue 和 Pull Request!
|
|
493
|
-
|
|
494
|
-
## 📄 许可证
|
|
495
|
-
|
|
496
|
-
MIT License
|
|
497
|
-
`;
|
|
498
|
-
await fs.writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
|
499
|
-
// 创建 pnpm-workspace.yaml (如果使用 pnpm)
|
|
500
|
-
if (options.packageManager === 'pnpm') {
|
|
501
|
-
const workspaceContent = `packages:
|
|
502
|
-
- '.'
|
|
503
|
-
`;
|
|
504
|
-
await fs.writeFile(path.join(projectPath, 'pnpm-workspace.yaml'), workspaceContent);
|
|
505
|
-
}
|
|
506
|
-
// 创建环境变量示例文件
|
|
507
|
-
const envExampleContent = `# Zhin Bot 环境变量配置示例
|
|
508
|
-
# 复制为 .env 文件并根据需要修改
|
|
509
|
-
|
|
510
|
-
# 调试模式
|
|
511
|
-
DEBUG=true
|
|
512
|
-
|
|
513
|
-
# 插件目录 (可选)
|
|
514
|
-
# PLUGIN_DIR=./src/plugins
|
|
515
|
-
|
|
516
|
-
# KOOK 机器人配置 (如果使用 KOOK 适配器)
|
|
517
|
-
# KOOK_TOKEN=your-kook-token
|
|
518
|
-
|
|
519
|
-
# ICQQ 机器人配置 (如果使用 ICQQ 适配器)
|
|
520
|
-
# ICQQ_SCAN_UIN=your-qq-number
|
|
521
|
-
# ICQQ_LOGIN_UIN=your-qq-number
|
|
522
|
-
# ICQQ_SIGN_ADDR=http://localhost:8080
|
|
523
|
-
|
|
524
|
-
# OneBot 机器人配置 (如果使用 OneBot 适配器)
|
|
525
|
-
# BOT_URL=ws://localhost:8080
|
|
526
|
-
# ACCESS_TOKEN=your-access-token
|
|
527
|
-
`;
|
|
528
|
-
await fs.writeFile(path.join(projectPath, '.env.example'), envExampleContent);
|
|
529
|
-
}
|
|
530
|
-
async function createConfigFile(projectPath, format) {
|
|
531
|
-
const configContent = getConfigContent(format);
|
|
532
|
-
let fileName;
|
|
533
|
-
switch (format) {
|
|
534
|
-
case 'ts':
|
|
535
|
-
fileName = 'zhin.config.ts';
|
|
536
|
-
break;
|
|
537
|
-
case 'js':
|
|
538
|
-
fileName = 'zhin.config.ts';
|
|
539
|
-
break;
|
|
540
|
-
default:
|
|
541
|
-
fileName = `zhin.config.${format}`;
|
|
542
|
-
}
|
|
543
|
-
await fs.writeFile(path.join(projectPath, fileName), configContent);
|
|
544
|
-
}
|
|
545
|
-
function getConfigContent(format) {
|
|
546
|
-
switch (format) {
|
|
547
|
-
case 'json':
|
|
548
|
-
return JSON.stringify({
|
|
549
|
-
bots: [
|
|
550
|
-
{
|
|
551
|
-
name: `${process.pid}`,
|
|
552
|
-
context: 'process'
|
|
553
|
-
}
|
|
554
|
-
],
|
|
555
|
-
plugin_dirs: [
|
|
556
|
-
'./src/plugins',
|
|
557
|
-
'node_modules',
|
|
558
|
-
'node_modules/@zhin.js'
|
|
559
|
-
],
|
|
560
|
-
plugins: [
|
|
561
|
-
'adapter-process',
|
|
562
|
-
'http',
|
|
563
|
-
'console',
|
|
564
|
-
'test-plugin'
|
|
565
|
-
],
|
|
566
|
-
debug: false
|
|
567
|
-
}, null, 2);
|
|
568
|
-
case 'yaml':
|
|
569
|
-
return `# Zhin Bot 配置文件
|
|
570
|
-
|
|
571
|
-
# 机器人配置
|
|
572
|
-
bots:
|
|
573
|
-
- name: \${process.pid}
|
|
574
|
-
context: process
|
|
575
|
-
|
|
576
|
-
# 插件目录
|
|
577
|
-
plugin_dirs:
|
|
578
|
-
- ./src/plugins
|
|
579
|
-
- node_modules
|
|
580
|
-
- node_modules/@zhin.js
|
|
581
|
-
# 要加载的插件列表
|
|
582
|
-
plugins:
|
|
583
|
-
- adapter-process
|
|
584
|
-
- http
|
|
585
|
-
- console
|
|
586
|
-
- test-plugin
|
|
587
|
-
|
|
588
|
-
# 调试模式
|
|
589
|
-
debug: false
|
|
590
|
-
`;
|
|
591
|
-
case 'toml':
|
|
592
|
-
return `# Zhin Bot 配置文件
|
|
593
|
-
|
|
594
|
-
# 机器人配置
|
|
595
|
-
[[bots]]
|
|
596
|
-
name = "\${process.pid}"
|
|
597
|
-
context = "process"
|
|
598
|
-
|
|
599
|
-
# 插件目录
|
|
600
|
-
plugin_dirs = ["./src/plugins", "node_modules", "node_modules/@zhin.js"]
|
|
601
|
-
|
|
602
|
-
# 要加载的插件列表
|
|
603
|
-
plugins = ["adapter-process", "http", "console", "test-plugin"]
|
|
604
|
-
|
|
605
|
-
# 调试模式
|
|
606
|
-
debug = false
|
|
607
|
-
`;
|
|
608
|
-
case 'ts':
|
|
609
|
-
return `import { defineConfig } from 'zhin.js';
|
|
610
|
-
|
|
611
|
-
export default defineConfig(async (env) => {
|
|
612
|
-
return {
|
|
613
|
-
// 机器人配置
|
|
614
|
-
bots: [
|
|
615
|
-
{
|
|
616
|
-
name: \`\${process.pid}\`,
|
|
617
|
-
context: 'process'
|
|
618
|
-
}
|
|
619
|
-
],
|
|
620
|
-
|
|
621
|
-
// 插件目录
|
|
622
|
-
plugin_dirs: [
|
|
623
|
-
env.PLUGIN_DIR || './src/plugins',
|
|
624
|
-
'node_modules',
|
|
625
|
-
'node_modules/@zhin.js'
|
|
626
|
-
],
|
|
627
|
-
|
|
628
|
-
// 要加载的插件列表
|
|
629
|
-
plugins: [
|
|
630
|
-
'adapter-process',
|
|
631
|
-
'http',
|
|
632
|
-
'console',
|
|
633
|
-
'test-plugin'
|
|
634
|
-
],
|
|
635
|
-
|
|
636
|
-
// 调试模式
|
|
637
|
-
debug: env.DEBUG === 'true'
|
|
638
|
-
};
|
|
639
|
-
});
|
|
640
|
-
`;
|
|
641
|
-
case 'js':
|
|
642
|
-
return `import { defineConfig } from 'zhin.js';
|
|
643
|
-
|
|
644
|
-
export default defineConfig(async (env) => {
|
|
645
|
-
return {
|
|
646
|
-
// 机器人配置
|
|
647
|
-
bots: [
|
|
648
|
-
{
|
|
649
|
-
name: \`\${process.pid}\`,
|
|
650
|
-
context: 'process'
|
|
651
|
-
}
|
|
652
|
-
],
|
|
653
|
-
|
|
654
|
-
// 插件目录
|
|
655
|
-
plugin_dirs: [
|
|
656
|
-
env.PLUGIN_DIR || './src/plugins',
|
|
657
|
-
'node_modules',
|
|
658
|
-
'node_modules/@zhin.js'
|
|
659
|
-
],
|
|
660
|
-
|
|
661
|
-
// 要加载的插件列表
|
|
662
|
-
plugins: [
|
|
663
|
-
'adapter-process',
|
|
664
|
-
'http',
|
|
665
|
-
'console',
|
|
666
|
-
'test-plugin'
|
|
667
|
-
],
|
|
668
|
-
|
|
669
|
-
// 调试模式
|
|
670
|
-
debug: env.DEBUG === 'true'
|
|
671
|
-
};
|
|
672
|
-
});
|
|
673
|
-
`;
|
|
674
|
-
default:
|
|
675
|
-
throw new Error(`不支持的配置格式: ${format}`);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
function getConfigExample(format) {
|
|
679
|
-
switch (format) {
|
|
680
|
-
case 'json':
|
|
681
|
-
return `\`\`\`json
|
|
682
|
-
{
|
|
683
|
-
"bots": [
|
|
684
|
-
{
|
|
685
|
-
"name": "\${process.pid}",
|
|
686
|
-
"context": "process"
|
|
687
|
-
}
|
|
688
|
-
],
|
|
689
|
-
"plugin_dirs": [
|
|
690
|
-
"./src/plugins",
|
|
691
|
-
"node_modules",
|
|
692
|
-
"node_modules/@zhin.js"
|
|
693
|
-
],
|
|
694
|
-
"plugins": [
|
|
695
|
-
"adapter-process",
|
|
696
|
-
"http",
|
|
697
|
-
"console",
|
|
698
|
-
"test-plugin"
|
|
699
|
-
],
|
|
700
|
-
"debug": false
|
|
701
|
-
}
|
|
702
|
-
\`\`\`
|
|
703
|
-
`;
|
|
704
|
-
case 'yaml':
|
|
705
|
-
return `\`\`\`yaml
|
|
706
|
-
# Zhin Bot 配置文件
|
|
707
|
-
|
|
708
|
-
# 机器人配置
|
|
709
|
-
bots:
|
|
710
|
-
- name: \${process.pid}
|
|
711
|
-
context: process
|
|
712
|
-
|
|
713
|
-
# 插件目录
|
|
714
|
-
plugin_dirs:
|
|
715
|
-
- ./src/plugins
|
|
716
|
-
- node_modules
|
|
717
|
-
|
|
718
|
-
# 要加载的插件列表
|
|
719
|
-
plugins:
|
|
720
|
-
- adapter-process
|
|
721
|
-
- http
|
|
722
|
-
- console
|
|
723
|
-
- test-plugin
|
|
724
|
-
|
|
725
|
-
# 调试模式
|
|
726
|
-
debug: false
|
|
727
|
-
\`\`\`
|
|
728
|
-
`;
|
|
729
|
-
case 'toml':
|
|
730
|
-
return `\`\`\`toml
|
|
731
|
-
# Zhin Bot 配置文件
|
|
732
|
-
|
|
733
|
-
# 机器人配置
|
|
734
|
-
[[bots]]
|
|
735
|
-
name = "\${process.pid}"
|
|
736
|
-
context = "process"
|
|
737
|
-
|
|
738
|
-
# 插件目录
|
|
739
|
-
plugin_dirs = ["./src/plugins", "node_modules"]
|
|
740
|
-
|
|
741
|
-
# 要加载的插件列表
|
|
742
|
-
plugins = ["adapter-process", "http", "console", "test-plugin"]
|
|
743
|
-
|
|
744
|
-
# 调试模式
|
|
745
|
-
debug = false
|
|
746
|
-
\`\`\`
|
|
747
|
-
`;
|
|
748
|
-
case 'ts':
|
|
749
|
-
return `\`\`\`typescript
|
|
750
|
-
import { defineConfig } from 'zhin.js';
|
|
751
|
-
|
|
752
|
-
export default defineConfig(async (env) => {
|
|
753
|
-
return {
|
|
754
|
-
// 机器人配置
|
|
755
|
-
bots: [
|
|
756
|
-
{
|
|
757
|
-
name: \`\${process.pid}\`,
|
|
758
|
-
context: 'process'
|
|
759
|
-
}
|
|
760
|
-
],
|
|
761
|
-
|
|
762
|
-
// 插件目录
|
|
763
|
-
plugin_dirs: [
|
|
764
|
-
env.PLUGIN_DIR || './src/plugins',
|
|
765
|
-
'node_modules'
|
|
766
|
-
],
|
|
767
|
-
|
|
768
|
-
// 要加载的插件列表
|
|
769
|
-
plugins: [
|
|
770
|
-
'adapter-process',
|
|
771
|
-
'http',
|
|
772
|
-
'console',
|
|
773
|
-
'test-plugin'
|
|
774
|
-
],
|
|
775
|
-
|
|
776
|
-
// 调试模式
|
|
777
|
-
debug: env.DEBUG === 'true'
|
|
778
|
-
};
|
|
779
|
-
});
|
|
780
|
-
\`\`\`
|
|
781
|
-
`;
|
|
782
|
-
case 'js':
|
|
783
|
-
return `\`\`\`javascript
|
|
784
|
-
import { defineConfig } from 'zhin.js';
|
|
785
|
-
|
|
786
|
-
export default defineConfig(async (env) => {
|
|
787
|
-
return {
|
|
788
|
-
// 机器人配置
|
|
789
|
-
bots: [
|
|
790
|
-
{
|
|
791
|
-
name: \`\${process.pid}\`,
|
|
792
|
-
context: 'process'
|
|
793
|
-
}
|
|
794
|
-
],
|
|
795
|
-
|
|
796
|
-
// 插件目录
|
|
797
|
-
plugin_dirs: [
|
|
798
|
-
env.PLUGIN_DIR || './src/plugins',
|
|
799
|
-
'node_modules'
|
|
800
|
-
],
|
|
801
|
-
|
|
802
|
-
// 要加载的插件列表
|
|
803
|
-
plugins: [
|
|
804
|
-
'adapter-process',
|
|
805
|
-
'http',
|
|
806
|
-
'console',
|
|
807
|
-
'test-plugin'
|
|
808
|
-
],
|
|
809
|
-
|
|
810
|
-
// 调试模式
|
|
811
|
-
debug: env.DEBUG === 'true'
|
|
812
|
-
};
|
|
813
|
-
});
|
|
814
|
-
\`\`\`
|
|
815
|
-
`;
|
|
816
|
-
default:
|
|
817
|
-
throw new Error(`不支持的配置格式: ${format}`);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
async function checkIfInWorkspace() {
|
|
821
|
-
let currentDir = process.cwd();
|
|
822
|
-
while (currentDir !== path.dirname(currentDir)) {
|
|
823
|
-
// 检查 pnpm-workspace.yaml
|
|
824
|
-
const pnpmWorkspacePath = path.join(currentDir, 'pnpm-workspace.yaml');
|
|
825
|
-
if (fs.existsSync(pnpmWorkspacePath)) {
|
|
826
|
-
return true;
|
|
827
|
-
}
|
|
828
|
-
// 检查 package.json 中的 workspaces 字段
|
|
829
|
-
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
830
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
831
|
-
try {
|
|
832
|
-
const packageJson = fs.readJsonSync(packageJsonPath);
|
|
833
|
-
if (packageJson.workspaces) {
|
|
834
|
-
return true;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
catch {
|
|
838
|
-
// 忽略错误,继续向上查找
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
currentDir = path.dirname(currentDir);
|
|
842
|
-
}
|
|
843
|
-
return false;
|
|
844
|
-
}
|
|
845
|
-
//# sourceMappingURL=init.js.map
|