@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.
- package/bin/reactpress-server.js +223 -15
- package/package.json +1 -1
package/bin/reactpress-server.js
CHANGED
|
@@ -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
|
-
|
|
121
|
+
let answers;
|
|
122
|
+
let dbTestResult = false;
|
|
47
123
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
254
|
+
const serverUrl = `http://localhost:${answers.serverPort}`;
|
|
255
|
+
|
|
256
|
+
// 创建.env文件 - 使用用户输入的配置
|
|
53
257
|
const envContent = `# Database Config
|
|
54
|
-
DB_HOST
|
|
55
|
-
DB_PORT
|
|
56
|
-
DB_USER
|
|
57
|
-
DB_PASSWD
|
|
58
|
-
DB_DATABASE
|
|
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
|
|
266
|
+
CLIENT_SITE_URL=${answers.clientUrl}
|
|
64
267
|
|
|
65
268
|
# Server Config
|
|
66
|
-
SERVER_SITE_URL
|
|
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:'));
|