-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev-server.js
More file actions
executable file
·130 lines (109 loc) · 3.61 KB
/
dev-server.js
File metadata and controls
executable file
·130 lines (109 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
#!/usr/bin/env node
/**
* Local Development Server for CaptureCascade Timeline
*
* Serves both Hugo static site (root) and React viewer (/viewer)
* to match the production deployment environment.
*/
const express = require('express');
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const app = express();
const PORT = process.env.PORT || 8080;
const HUGO_DIR = path.join(__dirname, 'hugo-site/public');
const VIEWER_DIR = path.join(__dirname, 'timeline/viewer/build');
const API_DIR = path.join(__dirname, 'timeline/data/api');
console.log('\n🚀 Starting CaptureCascade Timeline Development Server...\n');
// Check if builds exist
const hugoExists = fs.existsSync(HUGO_DIR);
const viewerExists = fs.existsSync(VIEWER_DIR);
if (!hugoExists) {
console.log('⚠️ Hugo build not found. Building Hugo site...');
buildHugo();
}
if (!viewerExists) {
console.log('⚠️ React viewer build not found. Building viewer...');
buildViewer();
}
function buildHugo() {
console.log('\n📦 Building Hugo static site...\n');
const hugo = spawn('hugo', [], {
cwd: path.join(__dirname, 'hugo-site'),
stdio: 'inherit',
shell: true
});
hugo.on('close', (code) => {
if (code === 0) {
console.log('✅ Hugo build complete!\n');
startServer();
} else {
console.error(`❌ Hugo build failed with code ${code}`);
process.exit(1);
}
});
}
function buildViewer() {
console.log('\n📦 Building React viewer...\n');
const npm = spawn('npm', ['run', 'build'], {
cwd: path.join(__dirname, 'timeline/viewer'),
stdio: 'inherit',
shell: true
});
npm.on('close', (code) => {
if (code === 0) {
console.log('✅ React viewer build complete!\n');
startServer();
} else {
console.error(`❌ React viewer build failed with code ${code}`);
process.exit(1);
}
});
}
function startServer() {
// Only start server if both builds exist
if (!fs.existsSync(HUGO_DIR) || !fs.existsSync(VIEWER_DIR)) {
return;
}
// Serve API data files at /api
app.use('/api', express.static(API_DIR));
// Serve React viewer at /viewer
app.use('/viewer', express.static(VIEWER_DIR));
// Handle React viewer routes (SPA fallback)
app.get('/viewer/*', (req, res) => {
res.sendFile(path.join(VIEWER_DIR, 'index.html'));
});
// Serve Hugo static site at root
app.use(express.static(HUGO_DIR));
// Hugo page routes fallback
app.get('*', (req, res) => {
// Check if file exists in Hugo build
const filePath = path.join(HUGO_DIR, req.path);
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
res.sendFile(filePath);
} else {
// Try index.html in the directory
const indexPath = path.join(filePath, 'index.html');
if (fs.existsSync(indexPath)) {
res.sendFile(indexPath);
} else {
// 404
res.status(404).sendFile(path.join(HUGO_DIR, '404.html'));
}
}
});
app.listen(PORT, () => {
console.log('\n✨ Development server running!\n');
console.log(` Local: http://localhost:${PORT}`);
console.log(` Hugo site: http://localhost:${PORT}/`);
console.log(` React viewer: http://localhost:${PORT}/viewer`);
console.log(` Events (static): http://localhost:${PORT}/events/`);
console.log(` API data: http://localhost:${PORT}/api/`);
console.log('\n📝 This matches the production deployment structure.\n');
console.log(' Press Ctrl+C to stop\n');
});
}
// If both builds already exist, start immediately
if (hugoExists && viewerExists) {
startServer();
}