feat: add Passenger app.js for Plesk deployment

Node.js entry point that serves static frontend files and proxies
/api/ requests to the FastAPI backend on port 8000.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
CCS Admin 2026-02-24 08:55:47 +00:00
parent 93884f3c8d
commit 47bd9c8a08

80
deploy/app.js Normal file
View file

@ -0,0 +1,80 @@
const http = require('http');
const fs = require('fs');
const path = require('path');
const DIST_DIR = path.join(__dirname, 'dist');
const MIME_TYPES = {
'.html': 'text/html; charset=utf-8',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.ttf': 'font/ttf',
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
};
function proxyToBackend(req, res) {
const options = {
hostname: '127.0.0.1',
port: 8000,
path: req.url,
method: req.method,
headers: { ...req.headers, host: '127.0.0.1:8000' },
};
const proxyReq = http.request(options, (proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res, { end: true });
});
proxyReq.on('error', (err) => {
console.error('Backend error:', err.message);
res.writeHead(502, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Backend unavailable' }));
});
req.pipe(proxyReq, { end: true });
}
function serveStatic(req, res) {
let urlPath = req.url.split('?')[0];
let filePath = path.join(DIST_DIR, urlPath === '/' ? 'index.html' : urlPath);
const ext = path.extname(filePath).toLowerCase();
fs.stat(filePath, (err, stats) => {
if (!err && stats.isFile()) {
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
res.writeHead(200, { 'Content-Type': contentType });
fs.createReadStream(filePath).pipe(res);
} else {
// SPA fallback
const indexPath = path.join(DIST_DIR, 'index.html');
fs.readFile(indexPath, (indexErr, data) => {
if (indexErr) {
res.writeHead(404);
res.end('Not Found');
} else {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(data);
}
});
}
});
}
const server = http.createServer((req, res) => {
if (req.url.startsWith('/api/') || req.url.startsWith('/docs') || req.url === '/openapi.json') {
proxyToBackend(req, res);
} else {
serveStatic(req, res);
}
});
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log('DAK Portal running on port ' + PORT);
});