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+ }
0 commit comments