create-zhin-app 1.0.8 → 1.0.10

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
@@ -5,9 +5,12 @@
5
5
  ## 核心特性
6
6
 
7
7
  - 🚀 **一键创建**: 使用标准的 `npm create` / `yarn create` / `pnpm create` 命令
8
- - **Workspace 结构**: 自动创建 pnpm workspace,支持插件开发
9
- - �🔧 **智能配置**: 自动安装 pnpm、项目依赖
10
- - 🎯 **交互式配置**: 选择运行时、配置格式
8
+ - 📦 **Workspace 结构**: 自动创建 pnpm workspace,支持插件开发
9
+ - 🔧 **智能配置**: 自动安装 pnpm、项目依赖
10
+ - 🎯 **交互式配置**: 选择运行时、配置格式、数据库类型
11
+ - 🗄️ **数据库支持**: 支持 SQLite、MySQL、PostgreSQL、MongoDB、Redis
12
+ - 🔐 **安全配置**: 自动生成 HTTP 认证和环境变量管理
13
+ - 📊 **日志配置**: 内置完整的日志等级和清理配置
11
14
  - 🌐 **零安装**: 无需全局安装,直接使用
12
15
 
13
16
  ## 快速开始
@@ -48,9 +51,18 @@ pnpm build
48
51
  1. **启动脚手架**: 当你运行 `npm create zhin-app` 时
49
52
  2. **检测 pnpm**: 自动检测并安装 pnpm(如果未安装)
50
53
  3. **交互式配置**: 询问项目名称、运行时、配置格式
51
- 4. **创建 Workspace**: 生成 pnpm workspace 结构
52
- 5. **自动安装依赖**: 在项目根目录执行 `pnpm install`
53
- 6. **完成提示**: 显示下一步操作指引
54
+ 4. **HTTP 认证配置**: 配置 Web 控制台登录信息
55
+ - 默认用户名:当前系统用户名
56
+ - 默认密码:随机生成 6 位字符串
57
+ 5. **数据库配置**: 选择数据库类型和连接参数
58
+ - SQLite (默认,零配置)
59
+ - MySQL、PostgreSQL、MongoDB、Redis
60
+ - 自动安装对应的数据库驱动包
61
+ 6. **创建 Workspace**: 生成 pnpm workspace 结构
62
+ 7. **生成配置文件**: 包含数据库、日志等完整配置
63
+ 8. **生成 .env 文件**: 保存 HTTP 认证和数据库连接信息
64
+ 9. **自动安装依赖**: 在项目根目录执行 `pnpm install`
65
+ 10. **完成提示**: 显示登录信息、数据库配置和下一步操作
54
66
 
55
67
  ## 支持的参数
56
68
 
@@ -64,10 +76,24 @@ npm create zhin-app my-bot
64
76
  npm create zhin-app my-awesome-bot
65
77
  ```
66
78
 
79
+ **交互式配置流程:**
80
+ 1. 📝 输入项目名称
81
+ 2. ⚙️ 选择运行时(Node.js / Bun)
82
+ 3. 📄 选择配置格式(TypeScript / JavaScript / YAML / JSON)
83
+ 4. 🔐 配置 Web 控制台登录信息
84
+ - 用户名(默认:当前系统用户名)
85
+ - 密码(默认:随机 6 位字符)
86
+ 5. 🗄️ 配置数据库
87
+ - SQLite(推荐,零配置)
88
+ - MySQL(主机、端口、用户名、密码、数据库名)
89
+ - PostgreSQL(主机、端口、用户名、密码、数据库名)
90
+ - MongoDB(连接字符串、数据库名)
91
+ - Redis(主机、端口、密码、数据库索引)
92
+
67
93
  ### 快速创建(跳过交互)
68
94
 
69
95
  ```bash
70
- # 使用默认配置(TypeScript + Node.js
96
+ # 使用默认配置(TypeScript + Node.js + 随机密码)
71
97
  npm create zhin-app my-bot -y
72
98
  # 或
73
99
  npm create zhin-app my-bot --yes
@@ -80,10 +106,15 @@ npm create zhin-app my-bot --yes
80
106
  | `[project-name]` | 项目名称(可选,会提示输入) | `my-zhin-bot` |
81
107
  | `-y, --yes` | 跳过交互,使用默认配置 | `false` |
82
108
 
83
- **默认配置:**
109
+ **默认配置(使用 `-y` 时):**
84
110
  - 配置格式: TypeScript (`zhin.config.ts`)
85
111
  - 运行时: Node.js
86
112
  - 包管理器: pnpm(自动安装)
113
+ - 数据库: SQLite (`./data/bot.db`, WAL 模式)
114
+ - HTTP 用户名: 当前系统用户名
115
+ - HTTP 密码: 随机生成 6 位字符
116
+ - 日志等级: INFO
117
+ - 日志清理: 7 天,10000 条记录
87
118
 
88
119
  ## 使用场景
89
120
 
@@ -141,10 +172,13 @@ my-awesome-bot/
141
172
  ├── tsconfig.json # TypeScript 根配置
142
173
  ├── pnpm-workspace.yaml # workspace 配置
143
174
  ├── .gitignore # Git 忽略规则
175
+ ├── .env # 环境变量(包含 HTTP 认证信息)
144
176
  ├── .env.example # 环境变量模板
145
177
  └── README.md # 项目说明文档
146
178
  ```
147
179
 
180
+ **⚠️ 重要**: `.env` 文件包含敏感信息(登录密码),已自动添加到 `.gitignore`,不会被提交到版本控制。
181
+
148
182
  **Workspace 配置 (`pnpm-workspace.yaml`):**
149
183
  ```yaml
150
184
  packages:
@@ -203,13 +237,19 @@ export default defineConfig<AppConfig>(async (env) => {
203
237
  name: `${process.pid}`,
204
238
  }
205
239
  ],
206
- plugin_dirs: ['./src/plugins', 'node_modules'],
240
+ plugin_dirs: ['./src/plugins', 'node_modules', 'node_modules/@zhin.js'],
207
241
  plugins: [
208
242
  'adapter-process',
209
243
  'http',
210
244
  'console',
211
- 'test-plugin'
245
+ 'example'
212
246
  ],
247
+ http: {
248
+ port: 8086,
249
+ username: process.env.HTTP_USERNAME || 'admin',
250
+ password: process.env.HTTP_PASSWORD || '123456',
251
+ base: '/api'
252
+ },
213
253
  debug: process.env.NODE_ENV === 'development'
214
254
  };
215
255
  });
@@ -233,6 +273,13 @@ pnpm dev
233
273
 
234
274
  访问 `http://localhost:8086` 查看 Web 控制台
235
275
 
276
+ **登录信息:**
277
+ - 用户名和密码在创建项目时已配置
278
+ - 保存在 `.env` 文件中
279
+ - 创建完成时会在终端显示
280
+
281
+ > 💡 **修改密码**: 编辑 `.env` 文件中的 `HTTP_USERNAME` 和 `HTTP_PASSWORD`
282
+
236
283
  ### 3. 创建插件
237
284
 
238
285
  ```bash
@@ -0,0 +1,5 @@
1
+ import { InitOptions, DatabaseConfig } from './types.js';
2
+ export declare function generateDatabaseEnvVars(config: DatabaseConfig): string;
3
+ export declare function generateDatabaseConfig(config: DatabaseConfig, format: 'ts' | 'js' | 'yaml' | 'json'): string;
4
+ export declare function createConfigFile(appPath: string, format: string, options: InitOptions): Promise<void>;
5
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGzD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA+CtE;AAGD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAgG5G;AAGD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,iBAiJ3F"}
package/lib/config.js ADDED
@@ -0,0 +1,271 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ // 生成数据库环境变量
4
+ export function generateDatabaseEnvVars(config) {
5
+ const envVars = [];
6
+ switch (config.dialect) {
7
+ case 'mysql':
8
+ envVars.push('# MySQL 数据库配置', `DB_HOST=${config.host || 'localhost'}`, `DB_PORT=${config.port || 3306}`, `DB_USER=${config.user || 'root'}`, `DB_PASSWORD=${config.password || ''}`, `DB_DATABASE=${config.database || 'zhin_bot'}`);
9
+ break;
10
+ case 'pg':
11
+ envVars.push('# PostgreSQL 数据库配置', `DB_HOST=${config.host || 'localhost'}`, `DB_PORT=${config.port || 5432}`, `DB_USER=${config.user || 'postgres'}`, `DB_PASSWORD=${config.password || ''}`, `DB_DATABASE=${config.database || 'zhin_bot'}`);
12
+ break;
13
+ case 'mongodb':
14
+ envVars.push('# MongoDB 数据库配置', `DB_URL=${config.url || 'mongodb://localhost:27017'}`, `DB_NAME=${config.dbName || 'zhin_bot'}`);
15
+ break;
16
+ case 'redis':
17
+ envVars.push('# Redis 数据库配置', `REDIS_HOST=${config.socket?.host || 'localhost'}`, `REDIS_PORT=${config.socket?.port || 6379}`, `REDIS_PASSWORD=${config.password || ''}`, `REDIS_DB=${config.database || 0}`);
18
+ break;
19
+ case 'sqlite':
20
+ default:
21
+ // SQLite 不需要额外的环境变量
22
+ break;
23
+ }
24
+ return envVars.length > 0 ? `\n\n${envVars.join('\n')}` : '';
25
+ }
26
+ // 生成数据库配置代码
27
+ export function generateDatabaseConfig(config, format) {
28
+ // 根据数据库类型生成使用环境变量的配置
29
+ let configObj = { dialect: config.dialect };
30
+ switch (config.dialect) {
31
+ case 'mysql':
32
+ configObj = {
33
+ dialect: 'mysql',
34
+ host: format === 'yaml' ? '${DB_HOST}' : 'env.DB_HOST',
35
+ port: format === 'yaml' ? '${DB_PORT}' : 'parseInt(env.DB_PORT || "3306")',
36
+ user: format === 'yaml' ? '${DB_USER}' : 'env.DB_USER',
37
+ password: format === 'yaml' ? '${DB_PASSWORD}' : 'env.DB_PASSWORD',
38
+ database: format === 'yaml' ? '${DB_DATABASE}' : 'env.DB_DATABASE'
39
+ };
40
+ break;
41
+ case 'pg':
42
+ configObj = {
43
+ dialect: 'pg',
44
+ host: format === 'yaml' ? '${DB_HOST}' : 'env.DB_HOST',
45
+ port: format === 'yaml' ? '${DB_PORT}' : 'parseInt(env.DB_PORT || "5432")',
46
+ user: format === 'yaml' ? '${DB_USER}' : 'env.DB_USER',
47
+ password: format === 'yaml' ? '${DB_PASSWORD}' : 'env.DB_PASSWORD',
48
+ database: format === 'yaml' ? '${DB_DATABASE}' : 'env.DB_DATABASE'
49
+ };
50
+ break;
51
+ case 'mongodb':
52
+ configObj = {
53
+ dialect: 'mongodb',
54
+ url: format === 'yaml' ? '${DB_URL}' : 'env.DB_URL',
55
+ dbName: format === 'yaml' ? '${DB_NAME}' : 'env.DB_NAME'
56
+ };
57
+ break;
58
+ case 'redis':
59
+ configObj = {
60
+ dialect: 'redis',
61
+ socket: {
62
+ host: format === 'yaml' ? '${REDIS_HOST}' : 'env.REDIS_HOST',
63
+ port: format === 'yaml' ? '${REDIS_PORT}' : 'parseInt(env.REDIS_PORT || "6379")'
64
+ },
65
+ password: format === 'yaml' ? '${REDIS_PASSWORD}' : 'env.REDIS_PASSWORD || undefined',
66
+ database: format === 'yaml' ? '${REDIS_DB}' : 'parseInt(env.REDIS_DB || "0")'
67
+ };
68
+ break;
69
+ case 'sqlite':
70
+ default:
71
+ configObj = config;
72
+ break;
73
+ }
74
+ switch (format) {
75
+ case 'ts':
76
+ case 'js':
77
+ if (config.dialect === 'sqlite') {
78
+ return `database: ${JSON.stringify(configObj, null, 2).replace(/^/gm, ' ').trim()},`;
79
+ }
80
+ else {
81
+ // 对于其他数据库,手动构建配置以保持可读性
82
+ let configLines = ['{'];
83
+ configLines.push(` dialect: '${configObj.dialect}',`);
84
+ Object.entries(configObj).forEach(([key, value]) => {
85
+ if (key === 'dialect')
86
+ return;
87
+ if (typeof value === 'object' && value !== null) {
88
+ configLines.push(` ${key}: {`);
89
+ Object.entries(value).forEach(([subKey, subValue]) => {
90
+ if (typeof subValue === 'string' && subValue.startsWith('env.')) {
91
+ configLines.push(` ${subKey}: ${subValue},`);
92
+ }
93
+ else if (typeof subValue === 'string' && subValue.includes('parseInt(')) {
94
+ configLines.push(` ${subKey}: ${subValue},`);
95
+ }
96
+ else {
97
+ configLines.push(` ${subKey}: '${subValue}',`);
98
+ }
99
+ });
100
+ configLines.push(' },');
101
+ }
102
+ else if (typeof value === 'string' && value.startsWith('env.')) {
103
+ configLines.push(` ${key}: ${value},`);
104
+ }
105
+ else if (typeof value === 'string' && value.includes('parseInt(')) {
106
+ configLines.push(` ${key}: ${value},`);
107
+ }
108
+ else {
109
+ configLines.push(` ${key}: '${value}',`);
110
+ }
111
+ });
112
+ configLines.push(' }');
113
+ return `database: ${configLines.join('\n ')},`;
114
+ }
115
+ case 'yaml':
116
+ return Object.entries(configObj)
117
+ .map(([key, value]) => ` ${key}: ${typeof value === 'object' ? JSON.stringify(value).replace(/"/g, '') : value}`)
118
+ .join('\n');
119
+ case 'json':
120
+ const jsonStr = JSON.stringify(configObj, null, 2).replace(/^/gm, ' ');
121
+ return ` "database": ${jsonStr},`;
122
+ default:
123
+ return '';
124
+ }
125
+ }
126
+ // 创建配置文件
127
+ export async function createConfigFile(appPath, format, options) {
128
+ const databaseConfig = options.database ? generateDatabaseConfig(options.database, format) : '';
129
+ const configMap = {
130
+ ts: ['zhin.config.ts',
131
+ `import { defineConfig, LogLevel } from 'zhin.js';
132
+
133
+ export default defineConfig(async (env) => {
134
+ return {
135
+ ${databaseConfig ? ` ${databaseConfig.replace(/^ /, '')}` : ''}
136
+ bots: [{
137
+ name: \`\${process.pid}\`,
138
+ context: 'process'
139
+ }],
140
+ log_level: LogLevel.INFO,
141
+ log: {
142
+ maxDays: 7,
143
+ maxRecords: 10000,
144
+ cleanupInterval: 24
145
+ },
146
+ plugin_dirs: [
147
+ env.PLUGIN_DIR || './src/plugins',
148
+ 'node_modules',
149
+ 'node_modules/@zhin.js'
150
+ ],
151
+ plugins: [
152
+ 'adapter-process',
153
+ 'http',
154
+ 'console',
155
+ 'example'
156
+ ],
157
+ http: {
158
+ port: 8086,
159
+ username: env.HTTP_USERNAME,
160
+ password: env.HTTP_PASSWORD,
161
+ base: '/api'
162
+ },
163
+ debug: env.DEBUG === 'true'
164
+ };
165
+ });
166
+ `],
167
+ js: ['zhin.config.js',
168
+ `import { defineConfig, LogLevel } from 'zhin.js';
169
+
170
+ export default defineConfig(async (env) => {
171
+ return {
172
+ ${databaseConfig ? ` ${databaseConfig.replace(/^ /, '')}` : ''}
173
+ bots: [{
174
+ name: \`\${process.pid}\`,
175
+ context: 'process'
176
+ }],
177
+ log_level: LogLevel.INFO,
178
+ log: {
179
+ maxDays: 7,
180
+ maxRecords: 10000,
181
+ cleanupInterval: 24
182
+ },
183
+ plugin_dirs: [
184
+ env.PLUGIN_DIR || './src/plugins',
185
+ 'node_modules',
186
+ 'node_modules/@zhin.js'
187
+ ],
188
+ plugins: [
189
+ 'adapter-process',
190
+ 'http',
191
+ 'console',
192
+ 'example'
193
+ ],
194
+ http: {
195
+ port: 8086,
196
+ username: env.HTTP_USERNAME,
197
+ password: env.HTTP_PASSWORD,
198
+ base: '/api'
199
+ },
200
+ debug: env.DEBUG === 'true'
201
+ };
202
+ });
203
+ `],
204
+ yaml: ['zhin.config.yml',
205
+ `${databaseConfig ? `database:\n${databaseConfig}\n\n` : ''}bots:
206
+ - name: \${process.pid}
207
+ context: process
208
+
209
+ log_level: 1
210
+ log:
211
+ maxDays: 7
212
+ maxRecords: 10000
213
+ cleanupInterval: 24
214
+
215
+ plugin_dirs:
216
+ - ./src/plugins
217
+ - node_modules
218
+ - node_modules/@zhin.js
219
+
220
+ plugins:
221
+ - adapter-process
222
+ - http
223
+ - console
224
+ - example
225
+
226
+ http:
227
+ port: 8086
228
+ username: \${HTTP_USERNAME}
229
+ password: \${HTTP_PASSWORD}
230
+ base: /api
231
+
232
+ debug: false
233
+ `],
234
+ json: ['zhin.config.json',
235
+ `{
236
+ ${databaseConfig ? `${databaseConfig}` : ''}
237
+ "bots": [{
238
+ "name": "\${process.pid}",
239
+ "context": "process"
240
+ }],
241
+ "log_level": 1,
242
+ "log": {
243
+ "maxDays": 7,
244
+ "maxRecords": 10000,
245
+ "cleanupInterval": 24
246
+ },
247
+ "plugin_dirs": [
248
+ "./src/plugins",
249
+ "node_modules",
250
+ "node_modules/@zhin.js"
251
+ ],
252
+ "plugins": [
253
+ "adapter-process",
254
+ "http",
255
+ "console",
256
+ "example"
257
+ ],
258
+ "http": {
259
+ "port": 8086,
260
+ "username": "\${HTTP_USERNAME}",
261
+ "password": "\${HTTP_PASSWORD}",
262
+ "base": "/api"
263
+ },
264
+ "debug": false
265
+ }
266
+ `]
267
+ };
268
+ const [filename, content] = configMap[format] || configMap.ts;
269
+ await fs.writeFile(path.join(appPath, filename), content);
270
+ }
271
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { DatabaseConfig } from './types.js';
2
+ export declare function configureDatabaseOptions(): Promise<DatabaseConfig>;
3
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,cAAc,CAAC,CA+BxE"}
@@ -0,0 +1,260 @@
1
+ import inquirer from 'inquirer';
2
+ // 配置数据库选项
3
+ export async function configureDatabaseOptions() {
4
+ const { dialect } = await inquirer.prompt([
5
+ {
6
+ type: 'list',
7
+ name: 'dialect',
8
+ message: '选择数据库类型:',
9
+ choices: [
10
+ { name: 'SQLite (推荐, 零配置)', value: 'sqlite' },
11
+ { name: 'MySQL', value: 'mysql' },
12
+ { name: 'PostgreSQL', value: 'pg' },
13
+ { name: 'MongoDB', value: 'mongodb' },
14
+ { name: 'Redis', value: 'redis' }
15
+ ],
16
+ default: 'sqlite'
17
+ }
18
+ ]);
19
+ switch (dialect) {
20
+ case 'sqlite':
21
+ return await configureSQLite();
22
+ case 'mysql':
23
+ return await configureMySQL();
24
+ case 'pg':
25
+ return await configurePostgreSQL();
26
+ case 'mongodb':
27
+ return await configureMongoDB();
28
+ case 'redis':
29
+ return await configureRedis();
30
+ default:
31
+ throw new Error(`未支持的数据库类型: ${dialect}`);
32
+ }
33
+ }
34
+ // SQLite 配置
35
+ async function configureSQLite() {
36
+ const { filename, mode } = await inquirer.prompt([
37
+ {
38
+ type: 'input',
39
+ name: 'filename',
40
+ message: 'SQLite 数据库文件路径:',
41
+ default: './data/bot.db',
42
+ validate: (input) => {
43
+ if (!input.trim())
44
+ return '文件路径不能为空';
45
+ return true;
46
+ }
47
+ },
48
+ {
49
+ type: 'list',
50
+ name: 'mode',
51
+ message: 'SQLite 模式:',
52
+ choices: [
53
+ { name: 'WAL (推荐, 并发性能好)', value: 'wal' },
54
+ { name: 'DELETE (默认)', value: 'delete' },
55
+ { name: 'MEMORY (内存数据库)', value: 'memory' }
56
+ ],
57
+ default: 'wal'
58
+ }
59
+ ]);
60
+ return {
61
+ dialect: 'sqlite',
62
+ filename,
63
+ mode
64
+ };
65
+ }
66
+ // MySQL 配置
67
+ async function configureMySQL() {
68
+ const config = await inquirer.prompt([
69
+ {
70
+ type: 'input',
71
+ name: 'host',
72
+ message: 'MySQL 主机地址:',
73
+ default: 'localhost'
74
+ },
75
+ {
76
+ type: 'input',
77
+ name: 'port',
78
+ message: 'MySQL 端口:',
79
+ default: '3306',
80
+ validate: (input) => {
81
+ const port = parseInt(input);
82
+ if (isNaN(port) || port < 1 || port > 65535) {
83
+ return '请输入有效的端口号 (1-65535)';
84
+ }
85
+ return true;
86
+ }
87
+ },
88
+ {
89
+ type: 'input',
90
+ name: 'user',
91
+ message: 'MySQL 用户名:',
92
+ default: 'root'
93
+ },
94
+ {
95
+ type: 'password',
96
+ name: 'password',
97
+ message: 'MySQL 密码:'
98
+ },
99
+ {
100
+ type: 'input',
101
+ name: 'database',
102
+ message: 'MySQL 数据库名:',
103
+ default: 'zhin_bot',
104
+ validate: (input) => {
105
+ if (!input.trim())
106
+ return '数据库名不能为空';
107
+ return true;
108
+ }
109
+ }
110
+ ]);
111
+ return {
112
+ dialect: 'mysql',
113
+ host: config.host,
114
+ port: parseInt(config.port),
115
+ user: config.user,
116
+ password: config.password,
117
+ database: config.database
118
+ };
119
+ }
120
+ // PostgreSQL 配置
121
+ async function configurePostgreSQL() {
122
+ const config = await inquirer.prompt([
123
+ {
124
+ type: 'input',
125
+ name: 'host',
126
+ message: 'PostgreSQL 主机地址:',
127
+ default: 'localhost'
128
+ },
129
+ {
130
+ type: 'input',
131
+ name: 'port',
132
+ message: 'PostgreSQL 端口:',
133
+ default: '5432',
134
+ validate: (input) => {
135
+ const port = parseInt(input);
136
+ if (isNaN(port) || port < 1 || port > 65535) {
137
+ return '请输入有效的端口号 (1-65535)';
138
+ }
139
+ return true;
140
+ }
141
+ },
142
+ {
143
+ type: 'input',
144
+ name: 'user',
145
+ message: 'PostgreSQL 用户名:',
146
+ default: 'postgres'
147
+ },
148
+ {
149
+ type: 'password',
150
+ name: 'password',
151
+ message: 'PostgreSQL 密码:'
152
+ },
153
+ {
154
+ type: 'input',
155
+ name: 'database',
156
+ message: 'PostgreSQL 数据库名:',
157
+ default: 'zhin_bot',
158
+ validate: (input) => {
159
+ if (!input.trim())
160
+ return '数据库名不能为空';
161
+ return true;
162
+ }
163
+ }
164
+ ]);
165
+ return {
166
+ dialect: 'pg',
167
+ host: config.host,
168
+ port: parseInt(config.port),
169
+ user: config.user,
170
+ password: config.password,
171
+ database: config.database
172
+ };
173
+ }
174
+ // MongoDB 配置
175
+ async function configureMongoDB() {
176
+ const { url, dbName } = await inquirer.prompt([
177
+ {
178
+ type: 'input',
179
+ name: 'url',
180
+ message: 'MongoDB 连接字符串:',
181
+ default: 'mongodb://localhost:27017',
182
+ validate: (input) => {
183
+ if (!input.trim())
184
+ return '连接字符串不能为空';
185
+ if (!input.startsWith('mongodb://') && !input.startsWith('mongodb+srv://')) {
186
+ return '请输入有效的 MongoDB 连接字符串';
187
+ }
188
+ return true;
189
+ }
190
+ },
191
+ {
192
+ type: 'input',
193
+ name: 'dbName',
194
+ message: 'MongoDB 数据库名:',
195
+ default: 'zhin_bot',
196
+ validate: (input) => {
197
+ if (!input.trim())
198
+ return '数据库名不能为空';
199
+ return true;
200
+ }
201
+ }
202
+ ]);
203
+ return {
204
+ dialect: 'mongodb',
205
+ url,
206
+ dbName
207
+ };
208
+ }
209
+ // Redis 配置
210
+ async function configureRedis() {
211
+ const config = await inquirer.prompt([
212
+ {
213
+ type: 'input',
214
+ name: 'host',
215
+ message: 'Redis 主机地址:',
216
+ default: 'localhost'
217
+ },
218
+ {
219
+ type: 'input',
220
+ name: 'port',
221
+ message: 'Redis 端口:',
222
+ default: '6379',
223
+ validate: (input) => {
224
+ const port = parseInt(input);
225
+ if (isNaN(port) || port < 1 || port > 65535) {
226
+ return '请输入有效的端口号 (1-65535)';
227
+ }
228
+ return true;
229
+ }
230
+ },
231
+ {
232
+ type: 'password',
233
+ name: 'password',
234
+ message: 'Redis 密码 (可选):'
235
+ },
236
+ {
237
+ type: 'input',
238
+ name: 'db',
239
+ message: 'Redis 数据库索引:',
240
+ default: '0',
241
+ validate: (input) => {
242
+ const db = parseInt(input);
243
+ if (isNaN(db) || db < 0) {
244
+ return '请输入有效的数据库索引 (>= 0)';
245
+ }
246
+ return true;
247
+ }
248
+ }
249
+ ]);
250
+ return {
251
+ dialect: 'redis',
252
+ socket: {
253
+ host: config.host,
254
+ port: parseInt(config.port)
255
+ },
256
+ password: config.password || undefined,
257
+ database: parseInt(config.db)
258
+ };
259
+ }
260
+ //# sourceMappingURL=database.js.map