Scratch space for learning atproto app development
1import events from "node:events";
2import type http from "node:http";
3import cors from "cors";
4import express, { type Express } from "express";
5import helmet from "helmet";
6import { pino } from "pino";
7
8import { createDb, migrateToLatest } from "#/db";
9import { env } from "#/env";
10import { Ingester } from "#/firehose/ingester";
11import errorHandler from "#/middleware/errorHandler";
12import requestLogger from "#/middleware/requestLogger";
13import { createRouter } from "#/routes";
14import type { AppContext } from "./config";
15
16export class Server {
17 constructor(
18 public app: express.Application,
19 public server: http.Server,
20 public ctx: AppContext
21 ) {}
22
23 static async create() {
24 const { NODE_ENV, HOST, PORT } = env;
25
26 const logger = pino({ name: "server start" });
27 const db = createDb(":memory:");
28 await migrateToLatest(db);
29 const ingester = new Ingester(db);
30 ingester.start();
31 const ctx = {
32 db,
33 ingester,
34 logger,
35 };
36
37 const app: Express = express();
38
39 // Set the application to trust the reverse proxy
40 app.set("trust proxy", true);
41
42 // TODO: middleware for sqlite server
43 // TODO: middleware for OAuth
44
45 // Middlewares
46 app.use(express.json());
47 app.use(express.urlencoded({ extended: true }));
48 app.use(cors({ origin: env.CORS_ORIGIN, credentials: true }));
49 app.use(helmet());
50
51 // Request logging
52 app.use(requestLogger);
53
54 // Routes
55 const router = createRouter(ctx);
56 app.use(router);
57
58 // Error handlers
59 app.use(errorHandler());
60
61 const server = app.listen(env.PORT);
62 await events.once(server, "listening");
63 logger.info(`Server (${NODE_ENV}) running on port http://${HOST}:${PORT}`);
64
65 return new Server(app, server, ctx);
66 }
67
68 async close() {
69 this.ctx.logger.info("sigint received, shutting down");
70 this.ctx.ingester.destroy();
71 return new Promise<void>((resolve) => {
72 this.server.close(() => {
73 this.ctx.logger.info("server closed");
74 resolve();
75 });
76 });
77 }
78}