106 lines
3.1 KiB
JavaScript
106 lines
3.1 KiB
JavaScript
import { createServer } from 'node:http';
|
|
import { readFileSync, statSync, existsSync } from 'node:fs';
|
|
import { extname, join } from 'node:path';
|
|
|
|
const PORT = parseInt(process.env.PORT || '8005', 10);
|
|
const CLIENT_DIR = new URL('./dist/client/', import.meta.url).pathname;
|
|
|
|
const MIME_TYPES = {
|
|
'.html': 'text/html',
|
|
'.css': 'text/css',
|
|
'.js': 'application/javascript',
|
|
'.mjs': 'application/javascript',
|
|
'.json': 'application/json',
|
|
'.png': 'image/png',
|
|
'.jpg': 'image/jpeg',
|
|
'.jpeg': 'image/jpeg',
|
|
'.gif': 'image/gif',
|
|
'.svg': 'image/svg+xml',
|
|
'.ico': 'image/x-icon',
|
|
'.webp': 'image/webp',
|
|
'.woff': 'font/woff',
|
|
'.woff2': 'font/woff2',
|
|
'.xml': 'application/xml',
|
|
'.txt': 'text/plain',
|
|
};
|
|
|
|
async function run() {
|
|
const handler = (await import('./dist/server/server.js')).default;
|
|
|
|
const server = createServer(async (req, res) => {
|
|
try {
|
|
const url = new URL(req.url, `http://${req.headers.host || 'localhost'}`);
|
|
let pathname = url.pathname;
|
|
|
|
// Serve static files from dist/client/
|
|
if (pathname === '/') pathname = '/index.html';
|
|
const filePath = join(CLIENT_DIR, pathname);
|
|
|
|
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
const ext = extname(filePath).toLowerCase();
|
|
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
const content = readFileSync(filePath);
|
|
res.statusCode = 200;
|
|
res.setHeader('Content-Type', contentType);
|
|
res.setHeader('Content-Length', content.length);
|
|
res.end(content);
|
|
return;
|
|
}
|
|
|
|
// Fall back to SSR handler
|
|
let body;
|
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
body = await new Promise((resolve) => {
|
|
const chunks = [];
|
|
req.on('data', (chunk) => chunks.push(chunk));
|
|
req.on('end', () => resolve(Buffer.concat(chunks)));
|
|
req.on('error', () => resolve(null));
|
|
});
|
|
}
|
|
|
|
const request = new Request(url, {
|
|
method: req.method,
|
|
headers: Object.entries(req.headers).map(([k, v]) => [k, Array.isArray(v) ? v.join(', ') : v]),
|
|
body: body || undefined,
|
|
});
|
|
|
|
const response = await handler.fetch(request, {}, {});
|
|
|
|
res.statusCode = response.status;
|
|
response.headers.forEach((value, key) => {
|
|
res.setHeader(key, value);
|
|
});
|
|
|
|
if (response.body) {
|
|
const reader = response.body.getReader();
|
|
const pump = () => {
|
|
reader.read().then(({ done, value }) => {
|
|
if (done) { res.end(); return; }
|
|
res.write(value);
|
|
pump();
|
|
}).catch(() => { res.end(); });
|
|
};
|
|
pump();
|
|
} else {
|
|
res.end();
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
if (!res.headersSent) {
|
|
res.statusCode = 500;
|
|
res.setHeader('Content-Type', 'text/plain');
|
|
res.end('Internal Server Error');
|
|
}
|
|
}
|
|
});
|
|
|
|
server.listen(PORT, () => {
|
|
console.log(`Promist server listening on port ${PORT}`);
|
|
});
|
|
}
|
|
|
|
run().catch((err) => {
|
|
console.error('Failed to start server:', err);
|
|
process.exit(1);
|
|
});
|