@fecommunity/reactpress-server 1.0.0-beta.8 → 1.0.0
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/LICENSE +21 -0
- package/README.md +281 -309
- package/bin/reactpress-server.js +173 -414
- package/dist/generate-swagger.d.ts +1 -0
- package/dist/generate-swagger.js +73 -0
- package/dist/generate-swagger.js.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.js +258 -39
- package/dist/main.js.map +1 -1
- package/dist/modules/setting/setting.service.js +34 -11
- package/dist/modules/setting/setting.service.js.map +1 -1
- package/dist/public/favicon.png +0 -0
- package/dist/public/index.html +439 -0
- package/dist/public/swagger/custom.css +11 -0
- package/dist/starter.d.ts +1 -0
- package/dist/starter.js +84 -0
- package/dist/starter.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +687 -60
- package/package.json +34 -25
- package/public/favicon.png +0 -0
- package/public/index.html +439 -0
- package/public/swagger/custom.css +11 -0
- package/dist/bootstrap.d.ts +0 -10
- package/dist/bootstrap.js +0 -57
- package/dist/bootstrap.js.map +0 -1
package/bin/reactpress-server.js
CHANGED
|
@@ -1,444 +1,203 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* ReactPress Server CLI Entry Point
|
|
5
|
+
* This script allows starting the ReactPress server via npx
|
|
6
|
+
* Supports both regular and PM2 startup modes
|
|
7
|
+
*/
|
|
8
|
+
|
|
5
9
|
const path = require('path');
|
|
6
10
|
const fs = require('fs');
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
const { spawn, spawnSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
// Capture the original working directory where npx was executed
|
|
14
|
+
// BUT prioritize the REACTPRESS_ORIGINAL_CWD environment variable if it exists
|
|
15
|
+
// This ensures consistency when running via pnpm dev from root directory
|
|
16
|
+
const originalCwd = process.env.REACTPRESS_ORIGINAL_CWD || process.cwd();
|
|
17
|
+
|
|
18
|
+
// Get command line arguments
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const usePM2 = args.includes('--pm2');
|
|
21
|
+
const showHelp = args.includes('--help') || args.includes('-h');
|
|
22
|
+
|
|
23
|
+
// Show help if requested
|
|
24
|
+
if (showHelp) {
|
|
25
|
+
console.log(`
|
|
26
|
+
ReactPress Server - NestJS-based backend API for ReactPress CMS
|
|
27
|
+
|
|
28
|
+
Usage:
|
|
29
|
+
npx @fecommunity/reactpress-server [options]
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
--pm2 Start server with PM2 process manager
|
|
33
|
+
--help, -h Show this help message
|
|
10
34
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
35
|
+
Examples:
|
|
36
|
+
npx @fecommunity/reactpress-server # Start server normally
|
|
37
|
+
npx @fecommunity/reactpress-server --pm2 # Start server with PM2
|
|
38
|
+
npx @fecommunity/reactpress-server --help # Show this help message
|
|
39
|
+
`);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Get the directory where this script is located
|
|
44
|
+
const binDir = __dirname;
|
|
45
|
+
const serverDir = path.join(binDir, '..');
|
|
46
|
+
const distPath = path.join(serverDir, 'dist', 'main.js');
|
|
47
|
+
const ecosystemPath = path.join(serverDir, 'ecosystem.config.js');
|
|
15
48
|
|
|
16
|
-
//
|
|
17
|
-
|
|
49
|
+
// Function to check if PM2 is installed
|
|
50
|
+
function isPM2Installed() {
|
|
18
51
|
try {
|
|
19
|
-
|
|
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();
|
|
52
|
+
require.resolve('pm2');
|
|
61
53
|
return true;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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}`));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
// Check if PM2 is installed globally
|
|
56
|
+
try {
|
|
57
|
+
spawnSync('pm2', ['--version'], { stdio: 'ignore' });
|
|
58
|
+
return true;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return false;
|
|
74
61
|
}
|
|
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
62
|
}
|
|
87
63
|
}
|
|
88
64
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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)')
|
|
98
|
-
.action(async (options) => {
|
|
99
|
-
console.log(chalk.blue('🚀 Initializing ReactPress Server...\n'));
|
|
100
|
-
|
|
101
|
-
const cwd = process.cwd();
|
|
102
|
-
const envPath = path.join(cwd, '.env');
|
|
103
|
-
|
|
104
|
-
// 检查.env文件是否已存在
|
|
105
|
-
if (fs.existsSync(envPath)) {
|
|
106
|
-
const { overwrite } = await inquirer.prompt([
|
|
107
|
-
{
|
|
108
|
-
type: 'confirm',
|
|
109
|
-
name: 'overwrite',
|
|
110
|
-
message: 'Configuration file (.env) already exists. Overwrite?',
|
|
111
|
-
default: false
|
|
112
|
-
}
|
|
113
|
-
]);
|
|
114
|
-
|
|
115
|
-
if (!overwrite) {
|
|
116
|
-
console.log(chalk.yellow('⚠️ Initialization cancelled.'));
|
|
117
|
-
process.exit(0);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
let answers;
|
|
122
|
-
let dbTestResult = false;
|
|
123
|
-
|
|
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
|
-
}
|
|
253
|
-
|
|
254
|
-
const serverUrl = `http://localhost:${answers.serverPort}`;
|
|
255
|
-
|
|
256
|
-
// 创建.env文件 - 使用用户输入的配置
|
|
257
|
-
const envContent = `# Database Config
|
|
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}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
# Client Config
|
|
266
|
-
CLIENT_SITE_URL=${answers.clientUrl}
|
|
267
|
-
|
|
268
|
-
# Server Config
|
|
269
|
-
SERVER_SITE_URL=${serverUrl}
|
|
270
|
-
`;
|
|
271
|
-
|
|
272
|
-
fs.writeFileSync(envPath, envContent);
|
|
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;
|
|
279
|
-
|
|
280
|
-
if (!options.skipDbSetup) {
|
|
281
|
-
console.log(chalk.yellow('\n🗄️ Database setup:'));
|
|
282
|
-
console.log(chalk.gray(`Please ensure your ${options.database} server is running and create the database:`));
|
|
283
|
-
console.log(chalk.cyan(`CREATE DATABASE reactpress;`));
|
|
284
|
-
console.log(chalk.gray(`CREATE USER 'reactpress'@'localhost' IDENTIFIED BY 'reactpress';`));
|
|
285
|
-
console.log(chalk.gray(`GRANT ALL PRIVILEGES ON reactpress.* TO 'reactpress'@'localhost';`));
|
|
286
|
-
console.log(chalk.gray(`FLUSH PRIVILEGES;`));
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
console.log(chalk.green('\n🎉 ReactPress Server initialized successfully!'));
|
|
290
|
-
console.log(chalk.cyan('\nNext steps:'));
|
|
291
|
-
console.log(chalk.gray('1. Start the server: npx @fecommunity/reactpress-server start'));
|
|
292
|
-
console.log(chalk.gray('2. Visit API: http://localhost:' + options.port + '/api'));
|
|
293
|
-
console.log(chalk.gray('3. API docs: http://localhost:' + options.port + '/api (Swagger UI)'));
|
|
65
|
+
// Function to install PM2
|
|
66
|
+
function installPM2() {
|
|
67
|
+
console.log('[ReactPress Server] Installing PM2...');
|
|
68
|
+
const installResult = spawnSync('npm', ['install', 'pm2', '--no-save'], {
|
|
69
|
+
stdio: 'inherit',
|
|
70
|
+
cwd: serverDir
|
|
294
71
|
});
|
|
72
|
+
|
|
73
|
+
if (installResult.status !== 0) {
|
|
74
|
+
console.error('[ReactPress Server] Failed to install PM2');
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
295
80
|
|
|
296
|
-
//
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
.action(async (options) => {
|
|
304
|
-
console.log(chalk.blue('🚀 Starting ReactPress Server...\n'));
|
|
305
|
-
|
|
306
|
-
const cwd = process.cwd();
|
|
307
|
-
const envPath = path.join(cwd, '.env');
|
|
308
|
-
|
|
309
|
-
// 检查.env文件是否存在
|
|
310
|
-
if (!fs.existsSync(envPath)) {
|
|
311
|
-
console.log(chalk.red('❌ Configuration file (.env) not found!'));
|
|
312
|
-
console.log(chalk.yellow('Please run: npx @fecommunity/reactpress-server init'));
|
|
81
|
+
// Function to start with PM2
|
|
82
|
+
function startWithPM2() {
|
|
83
|
+
// Check if PM2 is installed
|
|
84
|
+
if (!isPM2Installed()) {
|
|
85
|
+
// Try to install PM2
|
|
86
|
+
if (!installPM2()) {
|
|
87
|
+
console.error('[ReactPress Server] Cannot start with PM2');
|
|
313
88
|
process.exit(1);
|
|
314
89
|
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check if the server is built
|
|
93
|
+
if (!fs.existsSync(distPath)) {
|
|
94
|
+
console.log('[ReactPress Server] Server not built yet. Building...');
|
|
315
95
|
|
|
316
|
-
//
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
if (hasServerDir) {
|
|
322
|
-
// 在项目根目录,使用相对路径
|
|
323
|
-
serverMainPath = path.join(serverPath, 'dist', 'main.js');
|
|
324
|
-
const packageDir = serverPath;
|
|
325
|
-
|
|
326
|
-
// 检查构建文件是否存在
|
|
327
|
-
if (!fs.existsSync(serverMainPath)) {
|
|
328
|
-
console.log(chalk.yellow('⚠️ Built server not found, building...'));
|
|
329
|
-
try {
|
|
330
|
-
execSync('pnpm run build:server', { cwd: cwd, stdio: 'inherit' });
|
|
331
|
-
} catch (error) {
|
|
332
|
-
console.log(chalk.red('❌ Build failed'));
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
// 可能在独立安装的@reactpress/server包中
|
|
338
|
-
try {
|
|
339
|
-
const serverPackagePath = require.resolve('@fecommunity/reactpress-server/package.json');
|
|
340
|
-
const serverPackageDir = path.dirname(serverPackagePath);
|
|
341
|
-
serverMainPath = path.join(serverPackageDir, 'dist', 'main.js');
|
|
342
|
-
} catch (error) {
|
|
343
|
-
console.log(chalk.red('❌ ReactPress server package not found!'));
|
|
344
|
-
console.log(chalk.yellow('Please install: npm install @fecommunity/reactpress-server'));
|
|
345
|
-
process.exit(1);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// 设置环境变量
|
|
350
|
-
const env = {
|
|
351
|
-
...process.env,
|
|
352
|
-
NODE_ENV: options.dev ? 'development' : 'production'
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
if (options.port) {
|
|
356
|
-
env.SERVER_PORT = options.port;
|
|
357
|
-
}
|
|
96
|
+
// Try to build the server
|
|
97
|
+
const buildResult = spawnSync('npm', ['run', 'build'], {
|
|
98
|
+
stdio: 'inherit',
|
|
99
|
+
cwd: serverDir
|
|
100
|
+
});
|
|
358
101
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
console.log(chalk.yellow('🔄 Starting in development mode...'));
|
|
362
|
-
if (hasServerDir) {
|
|
363
|
-
execSync('pnpm run dev:server', {
|
|
364
|
-
cwd: cwd,
|
|
365
|
-
stdio: 'inherit',
|
|
366
|
-
env
|
|
367
|
-
});
|
|
368
|
-
} else {
|
|
369
|
-
console.log(chalk.yellow('⚠️ Development mode using built server (source code not available)'));
|
|
370
|
-
console.log(chalk.cyan('Starting server with NODE_ENV=development...'));
|
|
371
|
-
execSync(`node ${serverMainPath}`, {
|
|
372
|
-
cwd: process.cwd(),
|
|
373
|
-
stdio: 'inherit',
|
|
374
|
-
env
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
} else {
|
|
378
|
-
console.log(chalk.green('🌟 Starting in production mode...'));
|
|
379
|
-
execSync(`node ${serverMainPath}`, {
|
|
380
|
-
cwd: process.cwd(),
|
|
381
|
-
stdio: 'inherit',
|
|
382
|
-
env
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
} catch (error) {
|
|
386
|
-
console.log(chalk.red('❌ Failed to start server'));
|
|
102
|
+
if (buildResult.status !== 0) {
|
|
103
|
+
console.error('[ReactPress Server] Failed to build server');
|
|
387
104
|
process.exit(1);
|
|
388
105
|
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
.command
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('[ReactPress Server] Starting with PM2...');
|
|
109
|
+
|
|
110
|
+
// Use ecosystem.config.js if it exists, otherwise use direct command
|
|
111
|
+
let pm2Command = 'pm2';
|
|
112
|
+
try {
|
|
113
|
+
// Try to resolve PM2 path
|
|
114
|
+
pm2Command = path.join(serverDir, 'node_modules', '.bin', 'pm2');
|
|
115
|
+
if (!fs.existsSync(pm2Command)) {
|
|
116
|
+
pm2Command = 'pm2';
|
|
117
|
+
}
|
|
118
|
+
} catch (e) {
|
|
119
|
+
pm2Command = 'pm2';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check if ecosystem.config.js exists
|
|
123
|
+
if (fs.existsSync(ecosystemPath)) {
|
|
124
|
+
const pm2 = spawn(pm2Command, ['start', ecosystemPath], {
|
|
125
|
+
stdio: 'inherit',
|
|
126
|
+
cwd: serverDir
|
|
127
|
+
});
|
|
397
128
|
|
|
398
|
-
|
|
399
|
-
|
|
129
|
+
pm2.on('close', (code) => {
|
|
130
|
+
console.log(`[ReactPress Server] PM2 process exited with code ${code}`);
|
|
131
|
+
process.exit(code);
|
|
132
|
+
});
|
|
400
133
|
|
|
401
|
-
|
|
402
|
-
console.
|
|
403
|
-
console.log(chalk.yellow('This command should be run from the project root directory.'));
|
|
134
|
+
pm2.on('error', (error) => {
|
|
135
|
+
console.error('[ReactPress Server] Failed to start with PM2:', error);
|
|
404
136
|
process.exit(1);
|
|
405
|
-
}
|
|
137
|
+
});
|
|
138
|
+
} else {
|
|
139
|
+
// Fallback to direct start
|
|
140
|
+
const pm2 = spawn(pm2Command, ['start', distPath, '--name', 'reactpress-server'], {
|
|
141
|
+
stdio: 'inherit',
|
|
142
|
+
cwd: serverDir
|
|
143
|
+
});
|
|
406
144
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
console.log(chalk.red('❌ Build failed'));
|
|
145
|
+
pm2.on('close', (code) => {
|
|
146
|
+
console.log(`[ReactPress Server] PM2 process exited with code ${code}`);
|
|
147
|
+
process.exit(code);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
pm2.on('error', (error) => {
|
|
151
|
+
console.error('[ReactPress Server] Failed to start with PM2:', error);
|
|
415
152
|
process.exit(1);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
418
156
|
|
|
419
|
-
//
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
.
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
// 调用start命令的dev模式
|
|
428
|
-
const args = ['start', '--dev'];
|
|
429
|
-
if (options.port) {
|
|
430
|
-
args.push('--port', options.port);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// 重新调用当前脚本
|
|
434
|
-
const child = require('child_process').spawn('node', [__filename, ...args], {
|
|
157
|
+
// Function to start with regular Node.js
|
|
158
|
+
function startWithNode() {
|
|
159
|
+
// Check if the server is built
|
|
160
|
+
if (!fs.existsSync(distPath)) {
|
|
161
|
+
console.log('[ReactPress Server] Server not built yet. Building...');
|
|
162
|
+
|
|
163
|
+
// Try to build the server
|
|
164
|
+
const buildResult = spawnSync('npm', ['run', 'build'], {
|
|
435
165
|
stdio: 'inherit',
|
|
436
|
-
|
|
166
|
+
cwd: serverDir
|
|
437
167
|
});
|
|
438
168
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
169
|
+
if (buildResult.status !== 0) {
|
|
170
|
+
console.error('[ReactPress Server] Failed to build server');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ONLY set the environment variable if it's not already set
|
|
176
|
+
// This preserves the value set by set-env.js when running pnpm dev from root
|
|
177
|
+
if (!process.env.REACTPRESS_ORIGINAL_CWD) {
|
|
178
|
+
process.env.REACTPRESS_ORIGINAL_CWD = originalCwd;
|
|
179
|
+
} else {
|
|
180
|
+
console.log(`[ReactPress Server] Using existing REACTPRESS_ORIGINAL_CWD: ${process.env.REACTPRESS_ORIGINAL_CWD}`);
|
|
181
|
+
}
|
|
443
182
|
|
|
444
|
-
|
|
183
|
+
// Change to the server directory
|
|
184
|
+
process.chdir(serverDir);
|
|
185
|
+
|
|
186
|
+
// Set environment variables
|
|
187
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
|
|
188
|
+
|
|
189
|
+
// Import and run the server
|
|
190
|
+
try {
|
|
191
|
+
require(distPath);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error('[ReactPress Server] Failed to start server:', error);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Main execution
|
|
199
|
+
if (usePM2) {
|
|
200
|
+
startWithPM2();
|
|
201
|
+
} else {
|
|
202
|
+
startWithNode();
|
|
203
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|