61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import Fastify from 'fastify';
|
|
import fastifyWebsocket from '@fastify/websocket';
|
|
import { loadConfig } from './config.js';
|
|
import { getPool, closeDb } from './db.js';
|
|
import { registerHealthRoutes } from './routes/health.js';
|
|
import { registerTerminalRoutes } from './routes/terminals.js';
|
|
import { registerWsAttachRoute } from './ws/attach.js';
|
|
|
|
async function main(): Promise<void> {
|
|
const config = loadConfig();
|
|
|
|
const app = Fastify({
|
|
logger: { level: config.LOG_LEVEL },
|
|
});
|
|
|
|
app.removeContentTypeParser(['application/json']);
|
|
app.addContentTypeParser('application/json', { parseAs: 'string' }, (_req, body, done) => {
|
|
const str = (body as string) ?? '';
|
|
if (str.trim().length === 0) {
|
|
done(null, {});
|
|
return;
|
|
}
|
|
try {
|
|
done(null, JSON.parse(str));
|
|
} catch (err) {
|
|
done(err as Error, undefined);
|
|
}
|
|
});
|
|
|
|
getPool(config.DATABASE_URL);
|
|
|
|
await app.register(fastifyWebsocket);
|
|
|
|
registerHealthRoutes(app);
|
|
registerTerminalRoutes(app, config.TMUX_CONF_PATH);
|
|
registerWsAttachRoute(app, config.TMUX_CONF_PATH);
|
|
|
|
const shutdown = async (signal: string) => {
|
|
app.log.info(`received ${signal}, shutting down`);
|
|
try {
|
|
await app.close();
|
|
await closeDb();
|
|
process.exit(0);
|
|
} catch (err) {
|
|
app.log.error(err);
|
|
process.exit(1);
|
|
}
|
|
};
|
|
|
|
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
|
|
await app.listen({ port: config.PORT, host: config.HOST });
|
|
app.log.info(`booterm listening on http://${config.HOST}:${config.PORT}`);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Fatal startup error:', err);
|
|
process.exit(1);
|
|
});
|