Skip to content

Commit 3b1838f

Browse files
authored
feat: add npm publishing support for both client and server
feat: add npm publishing support for both client and server
2 parents b5bfb0b + 6782216 commit 3b1838f

30 files changed

+2884
-973
lines changed

.env

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ DB_USER=reactpress
55
DB_PASSWD=reactpress
66
DB_DATABASE=reactpress
77

8-
98
# Client Config
109
CLIENT_SITE_URL=http://localhost:3001
1110

client/bin/reactpress-client.js

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* ReactPress Client CLI Entry Point
5+
* This script allows starting the ReactPress client via npx
6+
* Supports both regular and PM2 startup modes
7+
*/
8+
9+
const path = require('path');
10+
const fs = require('fs');
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 Client - Next.js-based frontend for ReactPress CMS
27+
28+
Usage:
29+
npx @fecommunity/reactpress-client [options]
30+
31+
Options:
32+
--pm2 Start client with PM2 process manager
33+
--help, -h Show this help message
34+
35+
Examples:
36+
npx @fecommunity/reactpress-client # Start client normally
37+
npx @fecommunity/reactpress-client --pm2 # Start client with PM2
38+
npx @fecommunity/reactpress-client --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 clientDir = path.join(binDir, '..');
46+
const nextDir = path.join(clientDir, '.next');
47+
48+
// Function to check if PM2 is installed
49+
function isPM2Installed() {
50+
try {
51+
require.resolve('pm2');
52+
return true;
53+
} catch (e) {
54+
// Check if PM2 is installed globally
55+
try {
56+
spawnSync('pm2', ['--version'], { stdio: 'ignore' });
57+
return true;
58+
} catch (e) {
59+
return false;
60+
}
61+
}
62+
}
63+
64+
// Function to install PM2
65+
function installPM2() {
66+
console.log('[ReactPress Client] Installing PM2...');
67+
const installResult = spawnSync('npm', ['install', 'pm2', '--no-save'], {
68+
stdio: 'inherit',
69+
cwd: clientDir
70+
});
71+
72+
if (installResult.status !== 0) {
73+
console.error('[ReactPress Client] Failed to install PM2');
74+
return false;
75+
}
76+
77+
return true;
78+
}
79+
80+
// Function to start with PM2
81+
function startWithPM2() {
82+
// Check if PM2 is installed
83+
if (!isPM2Installed()) {
84+
// Try to install PM2
85+
if (!installPM2()) {
86+
console.error('[ReactPress Client] Cannot start with PM2');
87+
process.exit(1);
88+
}
89+
}
90+
91+
// Check if the client is built
92+
if (!fs.existsSync(nextDir)) {
93+
console.log('[ReactPress Client] Client not built yet. Building...');
94+
95+
// Try to build the client
96+
const buildResult = spawnSync('npm', ['run', 'build'], {
97+
stdio: 'inherit',
98+
cwd: clientDir
99+
});
100+
101+
if (buildResult.status !== 0) {
102+
console.error('[ReactPress Client] Failed to build client');
103+
process.exit(1);
104+
}
105+
}
106+
107+
console.log('[ReactPress Client] Starting with PM2...');
108+
109+
// Use PM2 to start the Next.js production server
110+
let pm2Command = 'pm2';
111+
try {
112+
// Try to resolve PM2 path
113+
pm2Command = path.join(clientDir, 'node_modules', '.bin', 'pm2');
114+
if (!fs.existsSync(pm2Command)) {
115+
pm2Command = 'pm2';
116+
}
117+
} catch (e) {
118+
pm2Command = 'pm2';
119+
}
120+
121+
// Start with PM2 using direct command
122+
const pm2 = spawn(pm2Command, ['start', 'npm', '--name', 'reactpress-client', '--', 'run', 'start'], {
123+
stdio: 'inherit',
124+
cwd: clientDir
125+
});
126+
127+
pm2.on('close', (code) => {
128+
console.log(`[ReactPress Client] PM2 process exited with code ${code}`);
129+
process.exit(code);
130+
});
131+
132+
pm2.on('error', (error) => {
133+
console.error('[ReactPress Client] Failed to start with PM2:', error);
134+
process.exit(1);
135+
});
136+
}
137+
138+
// Function to start with regular Node.js (npm start)
139+
function startWithNode() {
140+
// Check if the app is built
141+
if (!fs.existsSync(nextDir)) {
142+
console.log('[ReactPress Client] Client not built yet. Building...');
143+
144+
// Try to build the client
145+
const buildResult = spawnSync('npm', ['run', 'build'], {
146+
stdio: 'inherit',
147+
cwd: clientDir
148+
});
149+
150+
if (buildResult.status !== 0) {
151+
console.error('[ReactPress Client] Failed to build client');
152+
process.exit(1);
153+
}
154+
}
155+
156+
// ONLY set the environment variable if it's not already set
157+
// This preserves the value set by set-env.js when running pnpm dev from root
158+
if (!process.env.REACTPRESS_ORIGINAL_CWD) {
159+
process.env.REACTPRESS_ORIGINAL_CWD = originalCwd;
160+
} else {
161+
console.log(`[ReactPress Client] Using existing REACTPRESS_ORIGINAL_CWD: ${process.env.REACTPRESS_ORIGINAL_CWD}`);
162+
}
163+
164+
// Change to the client directory
165+
process.chdir(clientDir);
166+
167+
// Start with npm start
168+
console.log('[ReactPress Client] Starting with npm start...');
169+
const npmStart = spawn('npm', ['start'], {
170+
stdio: 'inherit',
171+
cwd: clientDir
172+
});
173+
174+
npmStart.on('close', (code) => {
175+
console.log(`[ReactPress Client] npm start process exited with code ${code}`);
176+
process.exit(code);
177+
});
178+
179+
npmStart.on('error', (error) => {
180+
console.error('[ReactPress Client] Failed to start with npm start:', error);
181+
process.exit(1);
182+
});
183+
}
184+
185+
// Main execution
186+
if (usePM2) {
187+
startWithPM2();
188+
} else {
189+
startWithNode();
190+
}

client/dev-server.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

client/package.json

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
{
22
"name": "@fecommunity/reactpress-client",
3-
"version": "1.0.1-beta.3",
3+
"version": "1.0.0-beta.22",
4+
"bin": {
5+
"reactpress-client": "./bin/reactpress-client.js"
6+
},
7+
"files": [
8+
".next/**/*",
9+
"bin/**/*",
10+
"public/**/*",
11+
"next.config.js",
12+
"server.js"
13+
],
414
"scripts": {
515
"prebuild": "rimraf .next",
616
"build": "next build",
717
"postbuild": "next-sitemap",
8-
"dev": "node dev-server.js",
9-
"start": "cross-env NODE_ENV=production node prod-server.js",
18+
"dev": "node server.js",
19+
"start": "cross-env NODE_ENV=production node server.js",
1020
"pm2": "pm2 start npm --name @fecommunity/reactpress-client -- start"
1121
},
1222
"dependencies": {
@@ -15,7 +25,7 @@
1525
"@ant-design/icons": "^4.7.0",
1626
"@ant-design/pro-layout": "7.19.11",
1727
"@monaco-editor/react": "^4.6.0",
18-
"@fecommunity/reactpress-config": "workspace:^1.0.0",
28+
"@fecommunity/reactpress-config": "workspace:*",
1929
"antd": "^5.24.4",
2030
"array-move": "^3.0.1",
2131
"axios": "^0.23.0",
@@ -75,4 +85,4 @@
7585
"tsconfig-paths-webpack-plugin": "^3.5.2",
7686
"typescript": "4.6.2"
7787
}
78-
}
88+
}

client/prod-server.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

client/public/sitemap.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
3-
<url><loc>http://localhost:3001</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.017Z</lastmod></url>
4-
<url><loc>http://localhost:3001/archives</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.018Z</lastmod></url>
5-
<url><loc>http://localhost:3001/knowledge</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.018Z</lastmod></url>
6-
<url><loc>http://localhost:3001/login</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.018Z</lastmod></url>
7-
<url><loc>http://localhost:3001/nav</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.018Z</lastmod></url>
8-
<url><loc>http://localhost:3001/rss</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-14T15:50:54.018Z</lastmod></url>
3+
<url><loc>http://localhost:3001</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
4+
<url><loc>http://localhost:3001/archives</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
5+
<url><loc>http://localhost:3001/knowledge</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
6+
<url><loc>http://localhost:3001/login</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
7+
<url><loc>http://localhost:3001/nav</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
8+
<url><loc>http://localhost:3001/rss</loc><changefreq>daily</changefreq><priority>0.7</priority><lastmod>2025-09-20T12:37:06.121Z</lastmod></url>
99
</urlset>

client/server.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const { config } = require('@fecommunity/reactpress-config');
2+
const cliProd = require('next/dist/cli/next-start');
3+
const cliDev = require('next/dist/cli/next-dev');
4+
const open = require('open');
5+
6+
const port = config.CLIENT_PORT || 3001;
7+
8+
try {
9+
// 这里根据环境判断,如果NODE_ENV=production, 就是生产
10+
if (process.env.NODE_ENV === 'production') {
11+
cliProd.nextStart(['-p', port]);
12+
} else {
13+
cliDev.nextDev(['-p', port]);
14+
}
15+
console.log(`[reactpress] 客户端已启动,端口:${port}`, `访问地址:http://localhost:${port}`);
16+
// 尝试自动打开
17+
open(`http://localhost:${port}`);
18+
} catch (err) {
19+
console.log(`[reactpress] 客户端启动失败!${err.message || err}`);
20+
}
File renamed without changes.
File renamed without changes.

config/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fecommunity/reactpress-config",
3-
"version": "1.0.0-beta.11",
3+
"version": "1.0.0-beta.34",
44
"description": "ReactPress Configuration - Environment and i18n configuration for ReactPress",
55
"author": "fecommunity",
66
"main": "./lib/index.js",
@@ -26,14 +26,16 @@
2626
},
2727
"files": [
2828
"lib",
29-
"src"
29+
"src",
30+
"locales"
3031
],
3132
"dependencies": {
3233
"dotenv": "^8.2.0",
3334
"fs-extra": "^10.0.0"
3435
},
3536
"devDependencies": {
37+
"@types/fs-extra": "^9.0.0",
3638
"@types/node": "^12.7.5",
37-
"@types/fs-extra": "^9.0.0"
39+
"typescript": "^5.9.2"
3840
}
3941
}

0 commit comments

Comments
 (0)