@fecommunity/reactpress-server 1.0.0-beta.4 → 1.0.0-beta.40
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 +81 -342
- package/bin/reactpress-server.js +175 -224
- package/dist/main.d.ts +5 -0
- package/dist/main.js +255 -39
- package/dist/main.js.map +1 -1
- package/dist/modules/setting/setting.service.js +35 -11
- package/dist/modules/setting/setting.service.js.map +1 -1
- package/dist/public/index.html +439 -0
- package/dist/starter.d.ts +1 -0
- package/dist/starter.js +101 -0
- package/dist/starter.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +559 -52
- package/package.json +31 -24
- package/public/index.html +439 -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,246 +1,197 @@
|
|
|
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
|
-
const inquirer = require('inquirer');
|
|
9
|
-
|
|
10
|
-
program
|
|
11
|
-
.name('@fecommunity/reactpress-server')
|
|
12
|
-
.description('ReactPress Server CLI')
|
|
13
|
-
.version('1.0.0');
|
|
14
|
-
|
|
15
|
-
// Init command - 初始化服务器配置
|
|
16
|
-
program
|
|
17
|
-
.command('init')
|
|
18
|
-
.description('Initialize ReactPress server configuration')
|
|
19
|
-
.option('-d, --database <type>', 'Database type (mysql|postgres)', 'mysql')
|
|
20
|
-
.option('-p, --port <port>', 'Server port', '3002')
|
|
21
|
-
.option('--skip-db-setup', 'Skip database setup')
|
|
22
|
-
.action(async (options) => {
|
|
23
|
-
console.log(chalk.blue('🚀 Initializing ReactPress Server...\n'));
|
|
24
|
-
|
|
25
|
-
const cwd = process.cwd();
|
|
26
|
-
const envPath = path.join(cwd, '.env');
|
|
27
|
-
|
|
28
|
-
// 检查.env文件是否已存在
|
|
29
|
-
if (fs.existsSync(envPath)) {
|
|
30
|
-
const { overwrite } = await inquirer.prompt([
|
|
31
|
-
{
|
|
32
|
-
type: 'confirm',
|
|
33
|
-
name: 'overwrite',
|
|
34
|
-
message: 'Configuration file (.env) already exists. Overwrite?',
|
|
35
|
-
default: false
|
|
36
|
-
}
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
|
-
if (!overwrite) {
|
|
40
|
-
console.log(chalk.yellow('⚠️ Initialization cancelled.'));
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// 使用基础配置模板,基于根目录的.env文件
|
|
46
|
-
console.log(chalk.cyan('📋 Creating configuration file based on default template...\n'));
|
|
47
|
-
|
|
48
|
-
// 生成JWT密钥
|
|
49
|
-
const jwtSecret = require('crypto').randomBytes(32).toString('hex');
|
|
50
|
-
console.log(chalk.green('🔐 Generated JWT secret'));
|
|
51
|
-
|
|
52
|
-
// 创建.env文件 - 基于根目录模板
|
|
53
|
-
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
|
|
59
|
-
|
|
60
|
-
# JWT Secret
|
|
61
|
-
JWT_SECRET=${jwtSecret}
|
|
62
|
-
|
|
63
|
-
# Client Config
|
|
64
|
-
CLIENT_SITE_URL=http://localhost:3001
|
|
65
|
-
|
|
66
|
-
# Server Config
|
|
67
|
-
SERVER_SITE_URL=http://localhost:${options.port}
|
|
68
|
-
SERVER_PORT=${options.port}
|
|
69
|
-
SERVER_API_PREFIX=/api
|
|
70
|
-
|
|
71
|
-
# Admin Config
|
|
72
|
-
ADMIN_USER=admin
|
|
73
|
-
ADMIN_PASSWD=admin
|
|
74
|
-
|
|
75
|
-
# Environment
|
|
76
|
-
NODE_ENV=development
|
|
77
|
-
`;
|
|
78
|
-
|
|
79
|
-
fs.writeFileSync(envPath, envContent);
|
|
80
|
-
console.log(chalk.green('✅ Configuration saved to .env file'));
|
|
81
|
-
|
|
82
|
-
if (!options.skipDbSetup) {
|
|
83
|
-
console.log(chalk.yellow('\n🗄️ Database setup:'));
|
|
84
|
-
console.log(chalk.gray(`Please ensure your ${options.database} server is running and create the database:`));
|
|
85
|
-
console.log(chalk.cyan(`CREATE DATABASE reactpress;`));
|
|
86
|
-
console.log(chalk.gray(`CREATE USER 'reactpress'@'localhost' IDENTIFIED BY 'reactpress';`));
|
|
87
|
-
console.log(chalk.gray(`GRANT ALL PRIVILEGES ON reactpress.* TO 'reactpress'@'localhost';`));
|
|
88
|
-
console.log(chalk.gray(`FLUSH PRIVILEGES;`));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
console.log(chalk.green('\n🎉 ReactPress Server initialized successfully!'));
|
|
92
|
-
console.log(chalk.cyan('\nNext steps:'));
|
|
93
|
-
console.log(chalk.gray('1. Start the server: npx @fecommunity/reactpress-server start'));
|
|
94
|
-
console.log(chalk.gray('2. Visit API: http://localhost:' + options.port + '/api'));
|
|
95
|
-
console.log(chalk.gray('3. API docs: http://localhost:' + options.port + '/api (Swagger UI)'));
|
|
96
|
-
});
|
|
11
|
+
const { spawn, spawnSync } = require('child_process');
|
|
97
12
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// 可能在独立安装的@reactpress/server包中
|
|
140
|
-
try {
|
|
141
|
-
const serverPackagePath = require.resolve('@fecommunity/reactpress-server/package.json');
|
|
142
|
-
const serverPackageDir = path.dirname(serverPackagePath);
|
|
143
|
-
serverMainPath = path.join(serverPackageDir, 'dist', 'main.js');
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.log(chalk.red('❌ ReactPress server package not found!'));
|
|
146
|
-
console.log(chalk.yellow('Please install: npm install @fecommunity/reactpress-server'));
|
|
147
|
-
process.exit(1);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 设置环境变量
|
|
152
|
-
const env = {
|
|
153
|
-
...process.env,
|
|
154
|
-
NODE_ENV: options.dev ? 'development' : 'production'
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
if (options.port) {
|
|
158
|
-
env.SERVER_PORT = options.port;
|
|
159
|
-
}
|
|
160
|
-
|
|
13
|
+
// Capture the original working directory where npx was executed
|
|
14
|
+
const originalCwd = process.cwd();
|
|
15
|
+
|
|
16
|
+
// Get command line arguments
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const usePM2 = args.includes('--pm2');
|
|
19
|
+
const showHelp = args.includes('--help') || args.includes('-h');
|
|
20
|
+
|
|
21
|
+
// Show help if requested
|
|
22
|
+
if (showHelp) {
|
|
23
|
+
console.log(`
|
|
24
|
+
ReactPress Server - NestJS-based backend API for ReactPress CMS
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
npx @fecommunity/reactpress-server [options]
|
|
28
|
+
|
|
29
|
+
Options:
|
|
30
|
+
--pm2 Start server with PM2 process manager
|
|
31
|
+
--help, -h Show this help message
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
npx @fecommunity/reactpress-server # Start server normally
|
|
35
|
+
npx @fecommunity/reactpress-server --pm2 # Start server with PM2
|
|
36
|
+
npx @fecommunity/reactpress-server --help # Show this help message
|
|
37
|
+
`);
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Get the directory where this script is located
|
|
42
|
+
const binDir = __dirname;
|
|
43
|
+
const serverDir = path.join(binDir, '..');
|
|
44
|
+
const distPath = path.join(serverDir, 'dist', 'main.js');
|
|
45
|
+
const ecosystemPath = path.join(serverDir, 'ecosystem.config.js');
|
|
46
|
+
|
|
47
|
+
// Function to check if PM2 is installed
|
|
48
|
+
function isPM2Installed() {
|
|
49
|
+
try {
|
|
50
|
+
require.resolve('pm2');
|
|
51
|
+
return true;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// Check if PM2 is installed globally
|
|
161
54
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
cwd: cwd,
|
|
167
|
-
stdio: 'inherit',
|
|
168
|
-
env
|
|
169
|
-
});
|
|
170
|
-
} else {
|
|
171
|
-
console.log(chalk.yellow('⚠️ Development mode using built server (source code not available)'));
|
|
172
|
-
console.log(chalk.cyan('Starting server with NODE_ENV=development...'));
|
|
173
|
-
execSync(`node ${serverMainPath}`, {
|
|
174
|
-
cwd: process.cwd(),
|
|
175
|
-
stdio: 'inherit',
|
|
176
|
-
env
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
console.log(chalk.green('🌟 Starting in production mode...'));
|
|
181
|
-
execSync(`node ${serverMainPath}`, {
|
|
182
|
-
cwd: process.cwd(),
|
|
183
|
-
stdio: 'inherit',
|
|
184
|
-
env
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
} catch (error) {
|
|
188
|
-
console.log(chalk.red('❌ Failed to start server'));
|
|
189
|
-
process.exit(1);
|
|
55
|
+
spawnSync('pm2', ['--version'], { stdio: 'ignore' });
|
|
56
|
+
return true;
|
|
57
|
+
} catch (e) {
|
|
58
|
+
return false;
|
|
190
59
|
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Function to install PM2
|
|
64
|
+
function installPM2() {
|
|
65
|
+
console.log('[ReactPress Server] Installing PM2...');
|
|
66
|
+
const installResult = spawnSync('npm', ['install', 'pm2', '--no-save'], {
|
|
67
|
+
stdio: 'inherit',
|
|
68
|
+
cwd: serverDir
|
|
191
69
|
});
|
|
70
|
+
|
|
71
|
+
if (installResult.status !== 0) {
|
|
72
|
+
console.error('[ReactPress Server] Failed to install PM2');
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
192
78
|
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const cwd = process.cwd();
|
|
201
|
-
const serverPath = path.join(cwd, 'server');
|
|
202
|
-
|
|
203
|
-
if (!fs.existsSync(serverPath)) {
|
|
204
|
-
console.log(chalk.red('❌ Server directory not found!'));
|
|
205
|
-
console.log(chalk.yellow('This command should be run from the project root directory.'));
|
|
79
|
+
// Function to start with PM2
|
|
80
|
+
function startWithPM2() {
|
|
81
|
+
// Check if PM2 is installed
|
|
82
|
+
if (!isPM2Installed()) {
|
|
83
|
+
// Try to install PM2
|
|
84
|
+
if (!installPM2()) {
|
|
85
|
+
console.error('[ReactPress Server] Cannot start with PM2');
|
|
206
86
|
process.exit(1);
|
|
207
87
|
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check if the server is built
|
|
91
|
+
if (!fs.existsSync(distPath)) {
|
|
92
|
+
console.log('[ReactPress Server] Server not built yet. Building...');
|
|
93
|
+
|
|
94
|
+
// Try to build the server
|
|
95
|
+
const buildResult = spawnSync('npm', ['run', 'build'], {
|
|
96
|
+
stdio: 'inherit',
|
|
97
|
+
cwd: serverDir
|
|
98
|
+
});
|
|
208
99
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
cwd: cwd,
|
|
212
|
-
stdio: 'inherit'
|
|
213
|
-
});
|
|
214
|
-
console.log(chalk.green('✅ Build completed successfully!'));
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.log(chalk.red('❌ Build failed'));
|
|
100
|
+
if (buildResult.status !== 0) {
|
|
101
|
+
console.error('[ReactPress Server] Failed to build server');
|
|
217
102
|
process.exit(1);
|
|
218
103
|
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.command
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const args = ['start', '--dev'];
|
|
231
|
-
if (options.port) {
|
|
232
|
-
args.push('--port', options.port);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('[ReactPress Server] Starting with PM2...');
|
|
107
|
+
|
|
108
|
+
// Use ecosystem.config.js if it exists, otherwise use direct command
|
|
109
|
+
let pm2Command = 'pm2';
|
|
110
|
+
try {
|
|
111
|
+
// Try to resolve PM2 path
|
|
112
|
+
pm2Command = path.join(serverDir, 'node_modules', '.bin', 'pm2');
|
|
113
|
+
if (!fs.existsSync(pm2Command)) {
|
|
114
|
+
pm2Command = 'pm2';
|
|
233
115
|
}
|
|
116
|
+
} catch (e) {
|
|
117
|
+
pm2Command = 'pm2';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if ecosystem.config.js exists
|
|
121
|
+
if (fs.existsSync(ecosystemPath)) {
|
|
122
|
+
const pm2 = spawn(pm2Command, ['start', ecosystemPath], {
|
|
123
|
+
stdio: 'inherit',
|
|
124
|
+
cwd: serverDir
|
|
125
|
+
});
|
|
234
126
|
|
|
235
|
-
|
|
236
|
-
|
|
127
|
+
pm2.on('close', (code) => {
|
|
128
|
+
console.log(`[ReactPress Server] PM2 process exited with code ${code}`);
|
|
129
|
+
process.exit(code);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
pm2.on('error', (error) => {
|
|
133
|
+
console.error('[ReactPress Server] Failed to start with PM2:', error);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
});
|
|
136
|
+
} else {
|
|
137
|
+
// Fallback to direct start
|
|
138
|
+
const pm2 = spawn(pm2Command, ['start', distPath, '--name', 'reactpress-server'], {
|
|
237
139
|
stdio: 'inherit',
|
|
238
|
-
|
|
140
|
+
cwd: serverDir
|
|
239
141
|
});
|
|
240
142
|
|
|
241
|
-
|
|
143
|
+
pm2.on('close', (code) => {
|
|
144
|
+
console.log(`[ReactPress Server] PM2 process exited with code ${code}`);
|
|
242
145
|
process.exit(code);
|
|
243
146
|
});
|
|
244
|
-
|
|
147
|
+
|
|
148
|
+
pm2.on('error', (error) => {
|
|
149
|
+
console.error('[ReactPress Server] Failed to start with PM2:', error);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Function to start with regular Node.js
|
|
156
|
+
function startWithNode() {
|
|
157
|
+
// Check if the server is built
|
|
158
|
+
if (!fs.existsSync(distPath)) {
|
|
159
|
+
console.log('[ReactPress Server] Server not built yet. Building...');
|
|
160
|
+
|
|
161
|
+
// Try to build the server
|
|
162
|
+
const buildResult = spawnSync('npm', ['run', 'build'], {
|
|
163
|
+
stdio: 'inherit',
|
|
164
|
+
cwd: serverDir
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (buildResult.status !== 0) {
|
|
168
|
+
console.error('[ReactPress Server] Failed to build server');
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Set the original working directory as an environment variable
|
|
174
|
+
// This allows the main application to know where the user executed npx from
|
|
175
|
+
process.env.REACTPRESS_ORIGINAL_CWD = originalCwd;
|
|
176
|
+
|
|
177
|
+
// Change to the server directory
|
|
178
|
+
process.chdir(serverDir);
|
|
179
|
+
|
|
180
|
+
// Set environment variables
|
|
181
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
|
|
182
|
+
|
|
183
|
+
// Import and run the server
|
|
184
|
+
try {
|
|
185
|
+
require(distPath);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.error('[ReactPress Server] Failed to start server:', error);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
245
191
|
|
|
246
|
-
|
|
192
|
+
// Main execution
|
|
193
|
+
if (usePM2) {
|
|
194
|
+
startWithPM2();
|
|
195
|
+
} else {
|
|
196
|
+
startWithNode();
|
|
197
|
+
}
|