atproto pastebin service: https://plonk.li
at plonkin 2.2 kB view raw
1import type http from "node:http"; 2import path from "node:path"; 3 4import express from "express"; 5import { OAuthClient } from "@atproto/oauth-client-node"; 6import { pino } from "pino"; 7import { Firehose } from "@atproto/sync"; 8import { createRouter } from "#/routes"; 9import { 10 createIdResolver, 11 createBidirectionalResolver, 12 BidirectionalResolver, 13} from "#/id-resolver"; 14import { createIngester } from "#/ingester"; 15import { createClient } from "#/auth/client"; 16import { Database, createDb, migrateToLatest } from "#/db"; 17import { env } from "#/lib"; 18 19export type Ctx = { 20 ingester: Firehose; 21 logger: pino.Logger; 22 oauthClient: OAuthClient; 23 resolver: BidirectionalResolver; 24 db: Database; 25}; 26 27export class Server { 28 constructor( 29 public app: express.Application, 30 public server: http.Server, 31 public ctx: Ctx, 32 ) {} 33 34 static async create() { 35 const db: Database = createDb(env.PLONK_DB_PATH); 36 await migrateToLatest(db); 37 const idResolver = createIdResolver(); 38 const ctx: Ctx = { 39 ingester: createIngester(db, idResolver), 40 logger: pino({ name: "server start" }), 41 oauthClient: await createClient(db), 42 resolver: createBidirectionalResolver(idResolver), 43 db: db, 44 }; 45 46 const app = express(); 47 app.set("trust proxy", true); 48 app.use(express.static(path.join(__dirname, "public"))); 49 app.set("views", path.join(__dirname, "views")); 50 app.set("view engine", "pug"); 51 52 const router = createRouter(ctx); 53 app.use(express.json()); 54 app.use(express.urlencoded({ extended: true })); 55 app.use(router); 56 app.use((_req, res) => res.sendStatus(404)); 57 58 const server = app.listen(env.PLONK_PORT); 59 60 return new Server(app, server, ctx); 61 } 62 63 async close() { 64 this.ctx.logger.info("shutting down"); 65 await this.ctx.ingester.destroy(); 66 return new Promise<void>((resolve) => { 67 this.server.close(() => { 68 this.ctx.logger.info("server closed"); 69 resolve(); 70 }); 71 }); 72 } 73} 74 75const run = async () => { 76 const server = await Server.create(); 77 78 const onCloseSignal = async () => { 79 setTimeout(() => process.exit(1), 10000).unref(); // Force shutdown after 10s 80 await server.close(); 81 process.exit(); 82 }; 83 84 process.on("SIGINT", onCloseSignal); 85 process.on("SIGTERM", onCloseSignal); 86}; 87 88run();