@gv-sh/specgen-app 0.6.5 โ 0.6.7
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/README.md +1 -1
- package/package.json +1 -1
- package/scripts/deploy.sh +201 -273
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# SpecGen App - Complete Platform
|
2
2
|
|
3
|
-
[](https://github.com/gv-sh/specgen-app)
|
4
4
|
|
5
5
|
A unified deployment package for the SpecGen speculative fiction generator platform. **Optimized for port 8080 deployment with low memory usage.**
|
6
6
|
|
package/package.json
CHANGED
package/scripts/deploy.sh
CHANGED
@@ -25,13 +25,7 @@ check_port() {
|
|
25
25
|
}
|
26
26
|
|
27
27
|
# Get absolute path of current working directory
|
28
|
-
|
29
|
-
if [ "$DRY_RUN" = true ]; then
|
30
|
-
PROJECT_DIR=$(pwd)
|
31
|
-
else
|
32
|
-
PROJECT_DIR=$(pwd)
|
33
|
-
fi
|
34
|
-
|
28
|
+
PROJECT_DIR=$(pwd)
|
35
29
|
echo "๐ Project directory: $PROJECT_DIR"
|
36
30
|
|
37
31
|
# ========================================
|
@@ -43,14 +37,19 @@ PLATFORM=$(uname -s)
|
|
43
37
|
if [ "$PLATFORM" = "Darwin" ]; then
|
44
38
|
echo "๐ Detected macOS"
|
45
39
|
PM2_CMD="npx pm2"
|
40
|
+
BIND_HOST="127.0.0.1" # macOS - bind to localhost for testing
|
46
41
|
elif [ "$PLATFORM" = "Linux" ]; then
|
47
42
|
echo "๐ง Detected Linux"
|
48
43
|
PM2_CMD="npx pm2"
|
44
|
+
BIND_HOST="0.0.0.0" # Linux - bind to all interfaces for public access
|
49
45
|
else
|
50
46
|
echo "โ ๏ธ Unknown platform: $PLATFORM"
|
51
47
|
PM2_CMD="npx pm2"
|
48
|
+
BIND_HOST="0.0.0.0"
|
52
49
|
fi
|
53
50
|
|
51
|
+
echo "๐ Server will bind to: $BIND_HOST"
|
52
|
+
|
54
53
|
# ========================================
|
55
54
|
# CLEANUP (Skip in dry-run for safety)
|
56
55
|
# ========================================
|
@@ -79,7 +78,6 @@ if [ "$DRY_RUN" = false ]; then
|
|
79
78
|
rm -rf logs/* 2>/dev/null || true
|
80
79
|
else
|
81
80
|
echo "๐งช DRY RUN: Skipping cleanup (existing processes will remain)"
|
82
|
-
echo " This is a safe test that won't affect your system"
|
83
81
|
fi
|
84
82
|
|
85
83
|
# ========================================
|
@@ -88,74 +86,39 @@ fi
|
|
88
86
|
|
89
87
|
echo "๐ Checking prerequisites..."
|
90
88
|
|
91
|
-
# Check Node.js version
|
89
|
+
# Check Node.js version
|
92
90
|
NODE_VERSION=$(node --version | sed 's/v//' | cut -d. -f1)
|
93
91
|
if [ "$DRY_RUN" = true ]; then
|
94
|
-
# More lenient for dry-run testing
|
95
92
|
if [ "$NODE_VERSION" -lt 18 ]; then
|
96
93
|
echo "โ Node.js 18+ required for testing. Current version: $(node --version)"
|
97
|
-
if [ "$PLATFORM" = "Darwin" ]; then
|
98
|
-
echo "Install with: brew install node"
|
99
|
-
fi
|
100
94
|
exit 1
|
101
95
|
else
|
102
|
-
echo "โ
Node.js version: $(node --version)
|
103
|
-
if [ "$NODE_VERSION" -lt 20 ]; then
|
104
|
-
echo " โ ๏ธ Note: Production deployment requires Node.js 20+"
|
105
|
-
fi
|
96
|
+
echo "โ
Node.js version: $(node --version)"
|
106
97
|
fi
|
107
98
|
else
|
108
|
-
# Strict for production
|
109
99
|
if [ "$NODE_VERSION" -lt 20 ]; then
|
110
100
|
echo "โ Node.js 20+ required for production. Current version: $(node --version)"
|
111
|
-
if [ "$PLATFORM" = "Darwin" ]; then
|
112
|
-
echo "Install with: brew install node@20"
|
113
|
-
else
|
114
|
-
echo "Install with: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs"
|
115
|
-
fi
|
116
101
|
exit 1
|
117
102
|
else
|
118
103
|
echo "โ
Node.js version: $(node --version)"
|
119
104
|
fi
|
120
105
|
fi
|
121
106
|
|
122
|
-
# Check npm
|
123
107
|
echo "โ
npm version: $(npm --version)"
|
124
108
|
|
125
|
-
# Check available memory
|
126
|
-
if [ "$PLATFORM" = "Darwin" ]; then
|
127
|
-
MEMORY_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}')
|
128
|
-
echo "โ
Available memory: ${MEMORY_GB}GB"
|
129
|
-
if [ "$MEMORY_GB" -lt 4 ]; then
|
130
|
-
echo "โ ๏ธ Warning: Less than 4GB RAM detected. Builds may be slow."
|
131
|
-
fi
|
132
|
-
elif [ "$PLATFORM" = "Linux" ]; then
|
133
|
-
MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}')
|
134
|
-
echo "โ
Available memory: ${MEMORY_GB}GB"
|
135
|
-
if [ "$MEMORY_GB" -lt 1 ]; then
|
136
|
-
echo "โ ๏ธ Warning: Less than 1GB RAM detected. Consider adding swap space."
|
137
|
-
fi
|
138
|
-
fi
|
139
|
-
|
140
|
-
# Check if we have required tools
|
141
|
-
echo "โ
Platform tools:"
|
142
|
-
echo " curl: $(which curl >/dev/null && echo "available" || echo "missing")"
|
143
|
-
echo " tar: $(which tar >/dev/null && echo "available" || echo "missing")"
|
144
|
-
echo " lsof: $(which lsof >/dev/null && echo "available" || echo "missing")"
|
145
|
-
|
146
109
|
# ========================================
|
147
110
|
# SETUP OPENAI API KEY
|
148
111
|
# ========================================
|
149
112
|
|
150
113
|
echo "๐ Setting up OpenAI API key..."
|
151
114
|
|
152
|
-
# In dry-run mode, always use a test key
|
153
115
|
if [ "$DRY_RUN" = true ]; then
|
154
116
|
echo "๐งช DRY RUN: Using test API key"
|
155
117
|
mkdir -p "$PROJECT_DIR/server"
|
156
118
|
echo "OPENAI_API_KEY=sk-test1234567890abcdef" > "$PROJECT_DIR/server/.env"
|
157
119
|
echo "NODE_ENV=production" >> "$PROJECT_DIR/server/.env"
|
158
120
|
echo "PORT=8080" >> "$PROJECT_DIR/server/.env"
|
121
|
+
echo "HOST=$BIND_HOST" >> "$PROJECT_DIR/server/.env"
|
159
122
|
elif [ ! -f "$PROJECT_DIR/server/.env" ] || grep -q "your_openai_api_key_here" "$PROJECT_DIR/server/.env" 2>/dev/null; then
|
160
123
|
if [ "$CI" = "true" ]; then
|
161
124
|
echo "CI mode - using test API key"
|
@@ -163,6 +126,7 @@ elif [ ! -f "$PROJECT_DIR/server/.env" ] || grep -q "your_openai_api_key_here" "
|
|
163
126
|
echo "OPENAI_API_KEY=sk-test1234" > "$PROJECT_DIR/server/.env"
|
164
127
|
echo "NODE_ENV=production" >> "$PROJECT_DIR/server/.env"
|
165
128
|
echo "PORT=8080" >> "$PROJECT_DIR/server/.env"
|
129
|
+
echo "HOST=$BIND_HOST" >> "$PROJECT_DIR/server/.env"
|
166
130
|
else
|
167
131
|
echo "โ ๏ธ OpenAI API key required for SpecGen to work."
|
168
132
|
echo "Enter your OpenAI API key (or press Enter to use test key): "
|
@@ -177,6 +141,7 @@ elif [ ! -f "$PROJECT_DIR/server/.env" ] || grep -q "your_openai_api_key_here" "
|
|
177
141
|
echo "OPENAI_API_KEY=$OPENAI_KEY" > "$PROJECT_DIR/server/.env"
|
178
142
|
echo "NODE_ENV=production" >> "$PROJECT_DIR/server/.env"
|
179
143
|
echo "PORT=8080" >> "$PROJECT_DIR/server/.env"
|
144
|
+
echo "HOST=$BIND_HOST" >> "$PROJECT_DIR/server/.env"
|
180
145
|
echo "โ
API key saved"
|
181
146
|
fi
|
182
147
|
fi
|
@@ -186,252 +151,254 @@ fi
|
|
186
151
|
# ========================================
|
187
152
|
|
188
153
|
echo "๐๏ธ Building application components..."
|
189
|
-
|
190
|
-
# Navigate to project directory
|
191
154
|
cd "$PROJECT_DIR"
|
192
155
|
|
193
|
-
# Install and build server
|
156
|
+
# Install and build server
|
194
157
|
if [ ! -f "server/index.js" ]; then
|
195
158
|
echo "๐ฆ Setting up server..."
|
196
159
|
|
197
|
-
# Clean up any existing server directory
|
198
160
|
rm -rf server
|
199
|
-
|
200
|
-
# Download and extract server
|
201
|
-
echo " Downloading server package..."
|
202
161
|
npm pack @gv-sh/specgen-server --loglevel=warn
|
203
|
-
|
204
|
-
echo " Extracting server package..."
|
205
162
|
tar -xzf gv-sh-specgen-server-*.tgz
|
206
163
|
|
207
|
-
# Move the extracted package to server directory
|
208
164
|
if [ -d "package" ]; then
|
209
165
|
mv package server
|
166
|
+
rm gv-sh-specgen-server-*.tgz
|
210
167
|
echo "โ
Server extracted successfully"
|
211
168
|
else
|
212
169
|
echo "โ Failed to extract server package"
|
213
|
-
ls -la
|
214
170
|
exit 1
|
215
171
|
fi
|
216
172
|
|
217
|
-
# Clean up the tar file
|
218
|
-
rm gv-sh-specgen-server-*.tgz
|
219
|
-
|
220
|
-
# Install server dependencies
|
221
|
-
echo " Installing server dependencies..."
|
222
173
|
cd server
|
223
174
|
echo "engine-strict=false" > .npmrc
|
224
175
|
npm install --no-fund --no-audit --production --maxsockets=2 --loglevel=warn
|
225
|
-
|
226
|
-
# Verify server files
|
227
|
-
if [ ! -f "index.js" ]; then
|
228
|
-
echo "โ Server index.js not found after installation"
|
229
|
-
echo "Server directory contents:"
|
230
|
-
ls -la
|
231
|
-
exit 1
|
232
|
-
fi
|
233
|
-
|
234
176
|
cd "$PROJECT_DIR"
|
177
|
+
|
178
|
+
# Install unified server that binds to 0.0.0.0
|
179
|
+
echo " ๐ง Installing unified server (binds to all interfaces)..."
|
180
|
+
cat > server/index.js << 'EOF'
|
181
|
+
// index.js - Unified server for port 8080 with public binding
|
182
|
+
/* global process */
|
183
|
+
require('dotenv').config();
|
184
|
+
const express = require('express');
|
185
|
+
const cors = require('cors');
|
186
|
+
const path = require('path');
|
187
|
+
const errorHandler = require('./middleware/errorHandler');
|
188
|
+
|
189
|
+
// Initialize Express app
|
190
|
+
const app = express();
|
191
|
+
const PORT = process.env.PORT || 8080;
|
192
|
+
const HOST = process.env.HOST || '0.0.0.0'; // Bind to all interfaces by default
|
193
|
+
|
194
|
+
// Middleware
|
195
|
+
app.use(cors());
|
196
|
+
app.use(express.json());
|
197
|
+
app.use(express.urlencoded({ extended: true }));
|
198
|
+
|
199
|
+
// Serve static files for admin interface at /admin
|
200
|
+
const adminBuildPath = path.join(__dirname, '../admin/build');
|
201
|
+
const fs = require('fs');
|
202
|
+
if (fs.existsSync(adminBuildPath)) {
|
203
|
+
app.use('/admin', express.static(adminBuildPath));
|
204
|
+
app.get('/admin/*', (req, res) => {
|
205
|
+
res.sendFile(path.join(adminBuildPath, 'index.html'));
|
206
|
+
});
|
207
|
+
console.log('โ
Admin interface available at /admin');
|
208
|
+
} else {
|
209
|
+
console.log('โ ๏ธ Admin build not found');
|
210
|
+
}
|
211
|
+
|
212
|
+
// Serve static files for user interface at /app
|
213
|
+
const userBuildPath = path.join(__dirname, '../user/build');
|
214
|
+
if (fs.existsSync(userBuildPath)) {
|
215
|
+
app.use('/app', express.static(userBuildPath));
|
216
|
+
app.get('/app/*', (req, res) => {
|
217
|
+
res.sendFile(path.join(userBuildPath, 'index.html'));
|
218
|
+
});
|
219
|
+
console.log('โ
User interface available at /app');
|
220
|
+
} else {
|
221
|
+
console.log('โ ๏ธ User build not found');
|
222
|
+
}
|
223
|
+
|
224
|
+
// Serve user interface as default at root
|
225
|
+
if (fs.existsSync(userBuildPath)) {
|
226
|
+
app.use('/', express.static(userBuildPath, { index: false }));
|
227
|
+
}
|
228
|
+
|
229
|
+
// API Routes
|
230
|
+
const categoryRoutes = require('./routes/categories');
|
231
|
+
const parameterRoutes = require('./routes/parameters');
|
232
|
+
const generateRoutes = require('./routes/generate');
|
233
|
+
const databaseRoutes = require('./routes/database');
|
234
|
+
const contentRoutes = require('./routes/content');
|
235
|
+
const settingsRoutes = require('./routes/settings');
|
236
|
+
|
237
|
+
app.use('/api/categories', categoryRoutes);
|
238
|
+
app.use('/api/parameters', parameterRoutes);
|
239
|
+
app.use('/api/generate', generateRoutes);
|
240
|
+
app.use('/api/database', databaseRoutes);
|
241
|
+
app.use('/api/content', contentRoutes);
|
242
|
+
app.use('/api/settings', settingsRoutes);
|
243
|
+
|
244
|
+
if (process.env.NODE_ENV !== 'test') {
|
245
|
+
const swaggerRoutes = require('./routes/swagger');
|
246
|
+
app.use('/api-docs', swaggerRoutes);
|
247
|
+
}
|
248
|
+
|
249
|
+
const healthRoutes = require('./routes/health');
|
250
|
+
app.use('/api/health', healthRoutes);
|
251
|
+
|
252
|
+
// Root route
|
253
|
+
app.get('/', (req, res) => {
|
254
|
+
if (fs.existsSync(userBuildPath)) {
|
255
|
+
res.sendFile(path.join(userBuildPath, 'index.html'));
|
256
|
+
} else {
|
257
|
+
const html = `
|
258
|
+
<!DOCTYPE html>
|
259
|
+
<html>
|
260
|
+
<head>
|
261
|
+
<title>SpecGen - Running on ${HOST}:${PORT}</title>
|
262
|
+
<style>
|
263
|
+
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; background: #f8f9fa; }
|
264
|
+
.nav-card { border: 1px solid #dee2e6; border-radius: 8px; padding: 20px; margin: 15px 0; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
265
|
+
.nav-card:hover { background-color: #f8f9fa; transform: translateY(-2px); transition: all 0.2s; }
|
266
|
+
a { text-decoration: none; color: #007bff; }
|
267
|
+
h1 { color: #343a40; text-align: center; }
|
268
|
+
.status { color: #28a745; font-weight: bold; text-align: center; background: #d4edda; padding: 10px; border-radius: 5px; margin: 20px 0; }
|
269
|
+
.binding { background: #e3f2fd; border: 1px solid #2196f3; padding: 15px; border-radius: 5px; margin: 20px 0; }
|
270
|
+
</style>
|
271
|
+
</head>
|
272
|
+
<body>
|
273
|
+
<h1>๐ SpecGen Platform</h1>
|
274
|
+
<div class="status">โ
Server running on ${HOST}:${PORT}</div>
|
275
|
+
|
276
|
+
<div class="binding">
|
277
|
+
<strong>๐ Network Binding:</strong> ${HOST === '0.0.0.0' ? 'Public access enabled (0.0.0.0)' : 'Local access only (' + HOST + ')'}
|
278
|
+
</div>
|
279
|
+
|
280
|
+
<div class="nav-card">
|
281
|
+
<h3><a href="/app">๐ฑ User Application</a></h3>
|
282
|
+
<p>Main SpecGen user interface</p>
|
283
|
+
</div>
|
284
|
+
|
285
|
+
<div class="nav-card">
|
286
|
+
<h3><a href="/admin">โ๏ธ Admin Panel</a></h3>
|
287
|
+
<p>Administrative interface</p>
|
288
|
+
</div>
|
289
|
+
|
290
|
+
<div class="nav-card">
|
291
|
+
<h3><a href="/api-docs">๐ API Documentation</a></h3>
|
292
|
+
<p>Interactive API documentation</p>
|
293
|
+
</div>
|
294
|
+
|
295
|
+
<div class="nav-card">
|
296
|
+
<h3><a href="/api/health">โค๏ธ Health Check</a></h3>
|
297
|
+
<p>System health monitoring</p>
|
298
|
+
</div>
|
299
|
+
</body>
|
300
|
+
</html>`;
|
301
|
+
res.send(html);
|
302
|
+
}
|
303
|
+
});
|
304
|
+
|
305
|
+
app.use(errorHandler);
|
306
|
+
|
307
|
+
if (require.main === module) {
|
308
|
+
app.listen(PORT, HOST, () => {
|
309
|
+
console.log(`๐ SpecGen server running on ${HOST}:${PORT}`);
|
310
|
+
console.log(`๐ฑ User App: http://${HOST}:${PORT}/app`);
|
311
|
+
console.log(`โ๏ธ Admin Panel: http://${HOST}:${PORT}/admin`);
|
312
|
+
console.log(`๐ API Docs: http://${HOST}:${PORT}/api-docs`);
|
313
|
+
console.log(`โค๏ธ Health Check: http://${HOST}:${PORT}/api/health`);
|
314
|
+
|
315
|
+
if (HOST === '0.0.0.0') {
|
316
|
+
console.log(`๐ Accessible from any IP address`);
|
317
|
+
} else {
|
318
|
+
console.log(`๐ Local access only (${HOST})`);
|
319
|
+
}
|
320
|
+
});
|
321
|
+
}
|
322
|
+
|
323
|
+
module.exports = app;
|
324
|
+
EOF
|
325
|
+
echo "โ
Unified server installed with public binding"
|
235
326
|
fi
|
236
327
|
|
237
|
-
#
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
if [ ! -d "admin" ]; then
|
242
|
-
# Clean up any existing admin directory
|
243
|
-
rm -rf admin
|
328
|
+
# Build admin and user (shortened for brevity)
|
329
|
+
for component in admin user; do
|
330
|
+
if [ ! -d "$component/build" ]; then
|
331
|
+
echo "๐ฑ Building $component interface..."
|
244
332
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
mv package admin
|
251
|
-
echo "โ
Admin extracted successfully"
|
252
|
-
else
|
253
|
-
echo "โ Failed to extract admin package"
|
254
|
-
exit 1
|
333
|
+
if [ ! -d "$component" ]; then
|
334
|
+
npm pack @gv-sh/specgen-$component --loglevel=warn
|
335
|
+
tar -xzf gv-sh-specgen-$component-*.tgz
|
336
|
+
mv package $component
|
337
|
+
rm gv-sh-specgen-$component-*.tgz
|
255
338
|
fi
|
256
339
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
echo " Installing admin dependencies..."
|
261
|
-
cd admin
|
262
|
-
echo "engine-strict=false" > .npmrc
|
263
|
-
# Install ALL dependencies for build process
|
264
|
-
npm install --no-fund --no-audit --maxsockets=2 --loglevel=warn
|
265
|
-
echo " Building admin interface..."
|
266
|
-
# Build with proper environment variables
|
267
|
-
GENERATE_SOURCEMAP=false SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/admin npm run build
|
268
|
-
cd "$PROJECT_DIR"
|
269
|
-
fi
|
270
|
-
|
271
|
-
# Install and build user
|
272
|
-
if [ ! -d "user/build" ]; then
|
273
|
-
echo "๐ค Building user interface..."
|
274
|
-
|
275
|
-
if [ ! -d "user" ]; then
|
276
|
-
# Clean up any existing user directory
|
277
|
-
rm -rf user
|
278
|
-
|
279
|
-
echo " Downloading user package..."
|
280
|
-
npm pack @gv-sh/specgen-user --loglevel=warn
|
281
|
-
tar -xzf gv-sh-specgen-user-*.tgz
|
340
|
+
cd $component
|
341
|
+
echo "engine-strict=false" > .npmrc
|
342
|
+
npm install --no-fund --no-audit --maxsockets=2 --loglevel=warn
|
282
343
|
|
283
|
-
if [
|
284
|
-
|
285
|
-
echo "โ
User extracted successfully"
|
344
|
+
if [ "$component" = "admin" ]; then
|
345
|
+
GENERATE_SOURCEMAP=false SKIP_PREFLIGHT_CHECK=true PUBLIC_URL=/admin npm run build
|
286
346
|
else
|
287
|
-
|
288
|
-
exit 1
|
347
|
+
GENERATE_SOURCEMAP=false SKIP_PREFLIGHT_CHECK=true REACT_APP_API_URL=/api PUBLIC_URL=/app npm run build
|
289
348
|
fi
|
290
|
-
|
291
|
-
rm gv-sh-specgen-user-*.tgz
|
349
|
+
cd "$PROJECT_DIR"
|
292
350
|
fi
|
293
|
-
|
294
|
-
echo " Installing user dependencies..."
|
295
|
-
cd user
|
296
|
-
echo "engine-strict=false" > .npmrc
|
297
|
-
# Install ALL dependencies for build process
|
298
|
-
npm install --no-fund --no-audit --maxsockets=2 --loglevel=warn
|
299
|
-
echo " Building user interface..."
|
300
|
-
# Build with proper environment variables
|
301
|
-
GENERATE_SOURCEMAP=false SKIP_PREFLIGHT_CHECK=true REACT_APP_API_URL=/api PUBLIC_URL=/app npm run build
|
302
|
-
cd "$PROJECT_DIR"
|
303
|
-
fi
|
351
|
+
done
|
304
352
|
|
305
353
|
# ========================================
|
306
354
|
# VERIFY BUILDS
|
307
355
|
# ========================================
|
308
356
|
|
309
357
|
echo "โ
Verifying builds..."
|
310
|
-
|
311
|
-
|
312
|
-
if [ ! -d "$PROJECT_DIR/admin/build" ]; then
|
313
|
-
echo "โ Admin build failed"
|
314
|
-
ls -la "$PROJECT_DIR/admin/" || echo "Admin directory not found"
|
358
|
+
if [ ! -d "admin/build" ] || [ ! -d "user/build" ] || [ ! -f "server/index.js" ]; then
|
359
|
+
echo "โ Build verification failed"
|
315
360
|
exit 1
|
316
361
|
fi
|
317
362
|
|
318
|
-
|
319
|
-
if [ ! -d "$PROJECT_DIR/user/build" ]; then
|
320
|
-
echo "โ User build failed"
|
321
|
-
ls -la "$PROJECT_DIR/user/" || echo "User directory not found"
|
322
|
-
exit 1
|
323
|
-
fi
|
324
|
-
|
325
|
-
# Check server
|
326
|
-
if [ ! -f "$PROJECT_DIR/server/index.js" ]; then
|
327
|
-
echo "โ Server index.js not found"
|
328
|
-
echo "Server directory contents:"
|
329
|
-
ls -la "$PROJECT_DIR/server/" || echo "Server directory not found"
|
330
|
-
exit 1
|
331
|
-
fi
|
332
|
-
|
333
|
-
echo "๐ Build verification:"
|
334
|
-
echo " Admin build: $(ls -la "$PROJECT_DIR/admin/build/" | wc -l) files"
|
335
|
-
echo " User build: $(ls -la "$PROJECT_DIR/user/build/" | wc -l) files"
|
336
|
-
echo " Server files: $(ls -la "$PROJECT_DIR/server/" | wc -l) files"
|
337
|
-
echo " โ
Server script: $PROJECT_DIR/server/index.js"
|
338
|
-
|
339
|
-
# Show some sample files to verify builds
|
340
|
-
echo "๐ Key files found:"
|
341
|
-
echo " Admin: $(ls "$PROJECT_DIR/admin/build/" | grep -E '\.(html|js|css)$' | head -3 | tr '\n' ' ')"
|
342
|
-
echo " User: $(ls "$PROJECT_DIR/user/build/" | grep -E '\.(html|js|css)$' | head -3 | tr '\n' ' ')"
|
343
|
-
echo " Server: $(ls "$PROJECT_DIR/server/" | grep -E '\.(js|json)$' | head -3 | tr '\n' ' ')"
|
363
|
+
echo "๐ All builds completed successfully"
|
344
364
|
|
345
365
|
# ========================================
|
346
|
-
# DEPLOYMENT
|
366
|
+
# DEPLOYMENT
|
347
367
|
# ========================================
|
348
368
|
|
349
369
|
if [ "$DRY_RUN" = true ]; then
|
350
|
-
echo ""
|
351
370
|
echo "๐งช DRY RUN: Testing server startup..."
|
352
|
-
|
353
|
-
# Test if the server can start
|
354
371
|
cd "$PROJECT_DIR"
|
372
|
+
cp server/.env .env 2>/dev/null || true
|
355
373
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
# Check if port 8080 is available for testing
|
360
|
-
if ! check_port 8080; then
|
361
|
-
echo " โ ๏ธ Port 8080 is in use, testing on port 8081 instead"
|
374
|
+
TEST_PORT=8080
|
375
|
+
if ! check_port $TEST_PORT; then
|
362
376
|
TEST_PORT=8081
|
363
|
-
sed -i.bak 's/PORT=8080/PORT=8081/' "$PROJECT_DIR/server/.env"
|
364
|
-
else
|
365
|
-
TEST_PORT=8080
|
366
377
|
fi
|
367
378
|
|
368
|
-
echo " Starting test server on
|
369
|
-
|
370
|
-
# Start server in background
|
371
|
-
(cd server && NODE_ENV=production PORT=$TEST_PORT node index.js) &
|
379
|
+
echo " Starting test server on $BIND_HOST:$TEST_PORT for 10 seconds..."
|
380
|
+
(cd server && NODE_ENV=production PORT=$TEST_PORT HOST=$BIND_HOST node index.js) &
|
372
381
|
SERVER_PID=$!
|
373
382
|
|
374
|
-
# Wait a bit for server to start
|
375
383
|
sleep 3
|
376
384
|
|
377
|
-
|
378
|
-
echo " Testing endpoints on port $TEST_PORT:"
|
379
|
-
|
385
|
+
echo " Testing endpoints:"
|
380
386
|
if curl -s http://localhost:$TEST_PORT/api/health >/dev/null 2>&1; then
|
381
387
|
echo " โ
Health endpoint: OK"
|
382
|
-
HEALTH_RESPONSE=$(curl -s http://localhost:$TEST_PORT/api/health)
|
383
|
-
echo " Status: $(echo $HEALTH_RESPONSE | grep -o '"status":"[^"]*"' | cut -d'"' -f4)"
|
384
388
|
else
|
385
389
|
echo " โ Health endpoint: FAILED"
|
386
390
|
fi
|
387
391
|
|
388
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$TEST_PORT/ 2>/dev/null || echo "000")
|
389
|
-
echo " ๐ Main page: HTTP $HTTP_CODE"
|
390
|
-
|
391
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$TEST_PORT/admin 2>/dev/null || echo "000")
|
392
|
-
echo " โ๏ธ Admin page: HTTP $HTTP_CODE"
|
393
|
-
|
394
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$TEST_PORT/app 2>/dev/null || echo "000")
|
395
|
-
echo " ๐ค User page: HTTP $HTTP_CODE"
|
396
|
-
|
397
|
-
# Stop test server
|
398
|
-
sleep 2
|
399
392
|
kill $SERVER_PID 2>/dev/null || true
|
400
393
|
wait $SERVER_PID 2>/dev/null || true
|
401
394
|
|
402
|
-
# Restore original .env if we changed it
|
403
|
-
if [ -f "$PROJECT_DIR/server/.env.bak" ]; then
|
404
|
-
mv "$PROJECT_DIR/server/.env.bak" "$PROJECT_DIR/server/.env"
|
405
|
-
fi
|
406
|
-
|
407
395
|
echo ""
|
408
396
|
echo "๐ DRY RUN COMPLETED!"
|
409
|
-
echo ""
|
410
|
-
echo "๐ Summary:"
|
411
|
-
echo " โ
All packages downloaded and extracted"
|
412
|
-
echo " โ
All dependencies installed"
|
413
|
-
echo " โ
React apps built successfully"
|
414
|
-
echo " โ
Server can start and respond"
|
415
|
-
echo ""
|
416
|
-
if [ "$NODE_VERSION" -lt 20 ]; then
|
417
|
-
echo "โ ๏ธ Note for AWS deployment:"
|
418
|
-
echo " Your Mac has Node.js $(node --version)"
|
419
|
-
echo " AWS deployment requires Node.js 20+"
|
420
|
-
echo " Make sure your AWS server has the right version"
|
421
|
-
echo ""
|
422
|
-
fi
|
423
397
|
echo "๐ Ready for production deployment!"
|
424
|
-
echo " Deploy to AWS with: npx @gv-sh/specgen-app deploy"
|
425
|
-
echo ""
|
426
|
-
echo "๐ง To test locally right now:"
|
427
|
-
echo " cd server && npm start"
|
428
|
-
echo " Open http://localhost:8080/"
|
429
398
|
|
430
399
|
else
|
431
|
-
# Real deployment with PM2
|
432
400
|
echo "๐ Starting PM2 deployment..."
|
433
401
|
|
434
|
-
# Create PM2 ecosystem configuration with absolute paths
|
435
402
|
cat > "$PROJECT_DIR/ecosystem.config.js" << EOF
|
436
403
|
module.exports = {
|
437
404
|
apps: [{
|
@@ -440,7 +407,8 @@ module.exports = {
|
|
440
407
|
cwd: '$PROJECT_DIR',
|
441
408
|
env: {
|
442
409
|
NODE_ENV: 'production',
|
443
|
-
PORT: 8080
|
410
|
+
PORT: 8080,
|
411
|
+
HOST: '$BIND_HOST'
|
444
412
|
},
|
445
413
|
instances: 1,
|
446
414
|
exec_mode: 'fork',
|
@@ -449,80 +417,40 @@ module.exports = {
|
|
449
417
|
out_file: '$PROJECT_DIR/logs/out.log',
|
450
418
|
log_file: '$PROJECT_DIR/logs/combined.log',
|
451
419
|
time: true,
|
452
|
-
watch: false
|
453
|
-
ignore_watch: ['node_modules', 'logs', '*.log'],
|
454
|
-
restart_delay: 1000,
|
455
|
-
max_restarts: 10,
|
456
|
-
min_uptime: '10s'
|
420
|
+
watch: false
|
457
421
|
}]
|
458
422
|
}
|
459
423
|
EOF
|
460
424
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
# Copy .env to project root for PM2
|
465
|
-
cp "$PROJECT_DIR/server/.env" "$PROJECT_DIR/.env" 2>/dev/null || true
|
425
|
+
mkdir -p logs
|
426
|
+
cp server/.env .env 2>/dev/null || true
|
466
427
|
|
467
|
-
# Final port check
|
468
428
|
if ! check_port 8080; then
|
469
|
-
echo "Port 8080 occupied, force cleaning..."
|
470
429
|
lsof -ti:8080 | xargs kill -9 2>/dev/null || true
|
471
430
|
sleep 2
|
472
431
|
fi
|
473
432
|
|
474
|
-
|
475
|
-
cd "$PROJECT_DIR"
|
476
|
-
echo "โถ๏ธ Starting SpecGen with PM2..."
|
477
|
-
|
478
|
-
NODE_ENV=production PORT=8080 $PM2_CMD start "$PROJECT_DIR/ecosystem.config.js"
|
433
|
+
NODE_ENV=production PORT=8080 HOST=$BIND_HOST $PM2_CMD start ecosystem.config.js
|
479
434
|
|
480
|
-
# Wait for startup and verify
|
481
435
|
sleep 5
|
482
436
|
|
483
|
-
# Verify deployment
|
484
|
-
echo "๐ Verifying deployment..."
|
485
|
-
|
486
437
|
if $PM2_CMD list | grep -q "online"; then
|
487
|
-
echo
|
488
|
-
|
489
|
-
if curl -s http://localhost:8080/api/health >/dev/null 2>&1; then
|
490
|
-
echo "โ
Health endpoint: OK"
|
491
|
-
else
|
492
|
-
echo "โ Health endpoint: FAILED"
|
493
|
-
fi
|
494
|
-
|
495
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/ 2>/dev/null)
|
496
|
-
echo "๐ Main page: HTTP $HTTP_CODE"
|
497
|
-
|
498
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/admin 2>/dev/null)
|
499
|
-
echo "โ๏ธ Admin page: HTTP $HTTP_CODE"
|
500
|
-
|
501
|
-
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/app 2>/dev/null)
|
502
|
-
echo "๐ค User page: HTTP $HTTP_CODE"
|
503
|
-
|
504
|
-
PUBLIC_IP=$(curl -s ifconfig.me 2>/dev/null || curl -s ipecho.net/plain 2>/dev/null || echo 'your-server')
|
438
|
+
PUBLIC_IP=$(curl -s ifconfig.me 2>/dev/null || echo 'your-server')
|
505
439
|
|
506
440
|
echo ""
|
507
441
|
echo "๐ SpecGen deployment completed!"
|
508
442
|
echo ""
|
509
443
|
echo "๐ Access your application at:"
|
510
444
|
echo " - Main page: http://$PUBLIC_IP:8080/"
|
511
|
-
echo " - User app: http://$PUBLIC_IP:8080/app"
|
512
|
-
echo " - Admin panel: http://$PUBLIC_IP:8080/admin"
|
513
|
-
echo " - API docs: http://$PUBLIC_IP:8080/api-docs"
|
514
|
-
echo " - Health check: http://$PUBLIC_IP:8080/api/health"
|
445
|
+
echo " - User app: http://$PUBLIC_IP:8080/app/"
|
446
|
+
echo " - Admin panel: http://$PUBLIC_IP:8080/admin/"
|
515
447
|
echo ""
|
516
|
-
echo "
|
517
|
-
echo "
|
518
|
-
echo " $PM2_CMD logs specgen # View logs"
|
519
|
-
echo " $PM2_CMD restart specgen # Restart"
|
448
|
+
echo "๐ง Binding: Server is bound to $BIND_HOST (${BIND_HOST:+publicly accessible})"
|
449
|
+
echo "๐ Management: npx pm2 status | npx pm2 logs specgen"
|
520
450
|
|
521
451
|
else
|
522
|
-
echo ""
|
523
452
|
echo "โ Deployment failed!"
|
524
|
-
|
525
|
-
echo "๐ Check status: $PM2_CMD status"
|
453
|
+
$PM2_CMD logs specgen --lines 10
|
526
454
|
exit 1
|
527
455
|
fi
|
528
456
|
fi
|