46 lines
1.8 KiB
JavaScript
46 lines
1.8 KiB
JavaScript
// server.js — Phusion Passenger / Plesk production entrypoint
|
|||
|
|
//
|
||
|
|
// Plesk sets PORT, then runs: node server.js
|
||
|
|
// We register the tsx ESM loader so TypeScript source is imported directly
|
||
|
|
// (no compile step needed), build the Fastify app, then start listening.
|
||
|
|
|
||
|
|
import { register } from 'tsx/esm/api';
|
||
|
|
register();
|
||
|
|
|
||
|
|
// server.ts exports buildServer(); env.ts exports the validated env object.
|
||
|
|
// Both are loaded through tsx so TypeScript is handled transparently.
|
||
|
|
const { buildServer } = await import('./apps/api/src/server.ts');
|
||
|
|
const { env } = await import('./apps/api/src/env.ts');
|
||
|
|
|
||
|
|
const app = await buildServer();
|
||
|
|
|
||
|
|
// ── Graceful shutdown ──────────────────────────────────────────────────────
|
||
|
|
async function shutdown(signal) {
|
||
|
|
app.log.info(`${signal} received — closing server`);
|
||
|
|
try {
|
||
|
|
await app.close();
|
||
|
|
} catch (err) {
|
||
|
|
app.log.error(err, 'error during shutdown');
|
||
|
|
}
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
||
|
|
process.on('SIGINT', () => void shutdown('SIGINT'));
|
||
|
|
|
||
|
|
// Surface hard crashes — Sentry is already initialised inside buildServer().
|
||
|
|
process.on('uncaughtException', (err) => {
|
||
|
|
app.log.error(err, 'uncaughtException');
|
||
|
|
process.exit(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
process.on('unhandledRejection', (reason) => {
|
||
|
|
app.log.error({ reason }, 'unhandledRejection');
|
||
|
|
process.exit(1);
|
||
|
|
});
|
||
|
|
|
||
|
|
// ── Start ──────────────────────────────────────────────────────────────────
|
||
|
|
// Passenger injects PORT; env.ts validates and defaults it to 8080 in dev.
|
||
|
|
await app.listen({ host: '0.0.0.0', port: env.PORT });
|
||
|
|
app.log.info(`eLegal Software ready · port ${env.PORT}`);
|