SPB Git

spb/earth-now Public License

earth-now.co — real-time planetary dashboard: live world metrics modeled, not streamed.

TypeScript 93% Shell 2.3% SQL 1.4% JavaScript 1.3% Dockerfile 1.2% CSS 0.8%
1.5 KB · 52 lines typescript
Raw Blame History
1/**2 * earth-now.co3 * Author:  Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File:    apps/api/src/server.ts6 * Purpose: Fastify app factory (buildApp for tests) + production listener on PORT (default 4000)7 */89import { pathToFileURL } from "node:url";10import Fastify, { type FastifyInstance } from "fastify";11import { startOpenNotifyPoller } from "./pollers/open-notify.js";12import { startUsgsPoller } from "./pollers/usgs.js";13import { registerRoutes } from "./routes.js";14import { ModelStore } from "./store.js";1516export interface BuildAppOptions {17  logger?: boolean;18  /** Start the RT pollers (additionally gated by ENABLE_RT_POLLERS !== "0"). */19  pollers?: boolean;20}2122export async function buildApp(options: BuildAppOptions = {}): Promise<FastifyInstance> {23  const app = Fastify({ logger: options.logger ?? true });2425  const store = new ModelStore();26  store.boot();27  await registerRoutes(app, store);2829  if (options.pollers ?? true) {30    const handles = [startUsgsPoller(store), startOpenNotifyPoller(store)];31    app.addHook("onClose", async () => {32      for (const handle of handles) handle.stop();33    });34  }3536  return app;37}3839const isMain =40  process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;4142if (isMain) {43  const app = await buildApp();44  const port = Number(process.env.PORT ?? 4000);45  try {46    await app.listen({ port, host: "0.0.0.0" });47  } catch (err) {48    app.log.error(err);49    process.exit(1);50  }51}52