@fecommunity/reactpress-server 1.0.0-beta.6 → 1.0.0-beta.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.
@@ -6,12 +6,86 @@ const path = require('path');
6
6
  const fs = require('fs');
7
7
  const chalk = require('chalk');
8
8
  const inquirer = require('inquirer');
9
+ const mysql = require('mysql2/promise');
9
10
 
10
11
  program
11
12
  .name('@fecommunity/reactpress-server')
12
13
  .description('ReactPress Server CLI')
13
14
  .version('1.0.0');
14
15
 
16
+ // Database connection testing function
17
+ async function testDatabaseConnection(config) {
18
+ try {
19
+ console.log(chalk.cyan('🔍 Testing database connection...'));
20
+
21
+ const connection = await mysql.createConnection({
22
+ host: config.dbHost,
23
+ port: parseInt(config.dbPort),
24
+ user: config.dbUser,
25
+ password: config.dbPassword
26
+ });
27
+
28
+ // Test basic connection
29
+ await connection.ping();
30
+ console.log(chalk.green('✅ Database connection successful!'));
31
+
32
+ // Check if database exists
33
+ const [databases] = await connection.execute(`SHOW DATABASES LIKE '${config.dbDatabase}'`);
34
+
35
+ if (databases.length === 0) {
36
+ console.log(chalk.yellow(`⚠️ Database '${config.dbDatabase}' does not exist.`));
37
+
38
+ const { createDb } = await inquirer.prompt([
39
+ {
40
+ type: 'confirm',
41
+ name: 'createDb',
42
+ message: `Create database '${config.dbDatabase}' now?`,
43
+ default: true
44
+ }
45
+ ]);
46
+
47
+ if (createDb) {
48
+ try {
49
+ await connection.execute(`CREATE DATABASE IF NOT EXISTS \`${config.dbDatabase}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`);
50
+ console.log(chalk.green(`✅ Database '${config.dbDatabase}' created successfully!`));
51
+ } catch (createError) {
52
+ console.log(chalk.red(`❌ Failed to create database: ${createError.message}`));
53
+ return false;
54
+ }
55
+ }
56
+ } else {
57
+ console.log(chalk.green(`✅ Database '${config.dbDatabase}' exists and is accessible.`));
58
+ }
59
+
60
+ await connection.end();
61
+ return true;
62
+
63
+ } catch (error) {
64
+ console.log(chalk.red('❌ Database connection failed:'));
65
+
66
+ if (error.code === 'ECONNREFUSED') {
67
+ console.log(chalk.yellow(' - Make sure MySQL server is running'));
68
+ console.log(chalk.yellow(` - Check if MySQL is listening on ${config.dbHost}:${config.dbPort}`));
69
+ } else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
70
+ console.log(chalk.yellow(' - Check username and password'));
71
+ console.log(chalk.yellow(' - Make sure user has proper permissions'));
72
+ } else {
73
+ console.log(chalk.yellow(` - Error: ${error.message}`));
74
+ }
75
+
76
+ const { retry } = await inquirer.prompt([
77
+ {
78
+ type: 'confirm',
79
+ name: 'retry',
80
+ message: 'Would you like to re-enter database configuration?',
81
+ default: true
82
+ }
83
+ ]);
84
+
85
+ return retry ? 'retry' : false;
86
+ }
87
+ }
88
+
15
89
  // Init command - 初始化服务器配置
16
90
  program
17
91
  .command('init')
@@ -19,6 +93,8 @@ program
19
93
  .option('-d, --database <type>', 'Database type (mysql|postgres)', 'mysql')
20
94
  .option('-p, --port <port>', 'Server port', '3002')
21
95
  .option('--skip-db-setup', 'Skip database setup')
96
+ .option('-y, --yes', 'Use default values without prompts')
97
+ .option('--auto', 'Alias for --yes (use default values without prompts)')
22
98
  .action(async (options) => {
23
99
  console.log(chalk.blue('🚀 Initializing ReactPress Server...\n'));
24
100
 
@@ -42,32 +118,164 @@ program
42
118
  }
43
119
  }
44
120
 
45
- // 使用完整的基础配置模板,包含客户端和服务端配置
46
- console.log(chalk.cyan('📋 Creating configuration file with essential settings...\n'));
121
+ let answers;
122
+ let dbTestResult = false;
47
123
 
48
- // 生成JWT密钥
49
- const jwtSecret = require('crypto').randomBytes(32).toString('hex');
50
- console.log(chalk.green('🔐 Generated JWT secret'));
124
+ // Configuration and database testing loop
125
+ while (!dbTestResult) {
126
+ if (options.yes || options.auto) {
127
+ // 使用默认值,不进行交互
128
+ console.log(chalk.cyan('📋 Using default configuration values...\n'));
129
+ answers = {
130
+ dbHost: '127.0.0.1',
131
+ dbPort: '3306',
132
+ dbUser: 'reactpress',
133
+ dbPassword: 'reactpress',
134
+ dbDatabase: 'reactpress',
135
+ clientUrl: 'http://localhost:3001',
136
+ serverPort: options.port || '3002',
137
+ skipDbSetup: options.skipDbSetup || false
138
+ };
139
+
140
+ // In auto mode, skip database testing if --skip-db-setup is provided
141
+ if (options.skipDbSetup) {
142
+ console.log(chalk.yellow('⚠️ Skipping database connection test (--skip-db-setup enabled)'));
143
+ dbTestResult = true;
144
+ } else {
145
+ dbTestResult = await testDatabaseConnection(answers);
146
+ if (dbTestResult === 'retry') {
147
+ console.log(chalk.yellow('\n⚠️ Switching to interactive mode for database configuration...\n'));
148
+ options.yes = false;
149
+ options.auto = false;
150
+ continue;
151
+ }
152
+ }
153
+ } else {
154
+ // 交互式配置收集
155
+ console.log(chalk.cyan('📋 Please configure your ReactPress server settings:\n'));
156
+
157
+ answers = await inquirer.prompt([
158
+ {
159
+ type: 'input',
160
+ name: 'dbHost',
161
+ message: 'Database Host:',
162
+ default: answers ? answers.dbHost : '127.0.0.1'
163
+ },
164
+ {
165
+ type: 'input',
166
+ name: 'dbPort',
167
+ message: 'Database Port:',
168
+ default: answers ? answers.dbPort : '3306',
169
+ validate: (input) => {
170
+ const port = parseInt(input);
171
+ return port > 0 && port <= 65535 ? true : 'Please enter a valid port number (1-65535)';
172
+ }
173
+ },
174
+ {
175
+ type: 'input',
176
+ name: 'dbUser',
177
+ message: 'Database Username:',
178
+ default: answers ? answers.dbUser : 'reactpress'
179
+ },
180
+ {
181
+ type: 'password',
182
+ name: 'dbPassword',
183
+ message: 'Database Password:',
184
+ default: answers ? answers.dbPassword : 'reactpress',
185
+ mask: '*'
186
+ },
187
+ {
188
+ type: 'input',
189
+ name: 'dbDatabase',
190
+ message: 'Database Name:',
191
+ default: answers ? answers.dbDatabase : 'reactpress'
192
+ },
193
+ {
194
+ type: 'input',
195
+ name: 'clientUrl',
196
+ message: 'Client Site URL:',
197
+ default: answers ? answers.clientUrl : 'http://localhost:3001',
198
+ validate: (input) => {
199
+ try {
200
+ new URL(input);
201
+ return true;
202
+ } catch {
203
+ return 'Please enter a valid URL (e.g., http://localhost:3001)';
204
+ }
205
+ }
206
+ },
207
+ {
208
+ type: 'input',
209
+ name: 'serverPort',
210
+ message: 'Server Port:',
211
+ default: answers ? answers.serverPort : (options.port || '3002'),
212
+ validate: (input) => {
213
+ const port = parseInt(input);
214
+ return port > 0 && port <= 65535 ? true : 'Please enter a valid port number (1-65535)';
215
+ }
216
+ },
217
+ {
218
+ type: 'confirm',
219
+ name: 'skipDbSetup',
220
+ message: 'Skip database setup instructions?',
221
+ default: false
222
+ }
223
+ ]);
224
+
225
+ // Test database connection
226
+ if (!answers.skipDbSetup) {
227
+ dbTestResult = await testDatabaseConnection(answers);
228
+ if (dbTestResult === 'retry') {
229
+ console.log(chalk.yellow('\n🔄 Let\'s try the database configuration again...\n'));
230
+ continue;
231
+ } else if (!dbTestResult) {
232
+ const { continueAnyway } = await inquirer.prompt([
233
+ {
234
+ type: 'confirm',
235
+ name: 'continueAnyway',
236
+ message: 'Continue with configuration file creation anyway?',
237
+ default: false
238
+ }
239
+ ]);
240
+
241
+ if (!continueAnyway) {
242
+ console.log(chalk.yellow('⚠️ Initialization cancelled.'));
243
+ process.exit(0);
244
+ }
245
+ dbTestResult = true; // Continue despite failed connection
246
+ }
247
+ } else {
248
+ console.log(chalk.yellow('⚠️ Skipping database connection test.'));
249
+ dbTestResult = true;
250
+ }
251
+ }
252
+ }
51
253
 
52
- // 创建.env文件 - 包含所有基础配置
254
+ const serverUrl = `http://localhost:${answers.serverPort}`;
255
+
256
+ // 创建.env文件 - 使用用户输入的配置
53
257
  const envContent = `# Database Config
54
- DB_HOST=127.0.0.1
55
- DB_PORT=3306
56
- DB_USER=reactpress
57
- DB_PASSWD=reactpress
58
- DB_DATABASE=reactpress
258
+ DB_HOST=${answers.dbHost}
259
+ DB_PORT=${answers.dbPort}
260
+ DB_USER=${answers.dbUser}
261
+ DB_PASSWD=${answers.dbPassword}
262
+ DB_DATABASE=${answers.dbDatabase}
59
263
 
60
- JWT_SECRET=${jwtSecret}
61
264
 
62
265
  # Client Config
63
- CLIENT_SITE_URL=http://localhost:3001
266
+ CLIENT_SITE_URL=${answers.clientUrl}
64
267
 
65
268
  # Server Config
66
- SERVER_SITE_URL=http://localhost:${options.port}
269
+ SERVER_SITE_URL=${serverUrl}
67
270
  `;
68
271
 
69
272
  fs.writeFileSync(envPath, envContent);
70
- console.log(chalk.green('✅ Configuration saved to .env file'));
273
+ console.log(chalk.green('\n✅ Configuration saved to .env file'));
274
+
275
+ // 更新 options 以使用用户输入的值
276
+ options.skipDbSetup = answers.skipDbSetup;
277
+ options.database = options.database || 'mysql';
278
+ options.port = answers.serverPort;
71
279
 
72
280
  if (!options.skipDbSetup) {
73
281
  console.log(chalk.yellow('\n🗄️ Database setup:'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fecommunity/reactpress-server",
3
- "version": "1.0.0-beta.6",
3
+ "version": "1.0.0-beta.8",
4
4
  "description": "ReactPress Server - NestJS-based backend API for ReactPress CMS",
5
5
  "author": "fecommunity",
6
6
  "license": "MIT",