WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
at main 99 lines 2.7 kB view raw
1import { serve } from "@hono/node-server"; 2import { loadConfig } from "./lib/config.js"; 3import { createAppContext, destroyAppContext } from "./lib/app-context.js"; 4import { createApp } from "./lib/create-app.js"; 5import { seedDefaultRoles } from "./lib/seed-roles.js"; 6 7async function main() { 8 // Load configuration 9 const config = loadConfig(); 10 11 // Create application context with all dependencies 12 const ctx = await createAppContext(config); 13 const { logger } = ctx; 14 15 // Wire BackfillManager ↔ FirehoseService (two-phase init: both exist now) 16 if (ctx.backfillManager) { 17 ctx.firehose.setBackfillManager(ctx.backfillManager); 18 ctx.backfillManager.setIndexer(ctx.firehose.getIndexer()); 19 } 20 21 // Seed default roles if enabled 22 if (process.env.SEED_DEFAULT_ROLES !== "false") { 23 logger.info("Seeding default roles"); 24 const result = await seedDefaultRoles(ctx); 25 logger.info("Default roles seeded", { 26 created: result.created, 27 skipped: result.skipped, 28 }); 29 } else { 30 logger.info("Role seeding disabled via SEED_DEFAULT_ROLES=false"); 31 } 32 33 // Create Hono app 34 const app = createApp(ctx); 35 36 // Start HTTP server 37 const server = serve( 38 { 39 fetch: app.fetch, 40 port: config.port, 41 }, 42 (info) => { 43 logger.info("Server started", { 44 url: `http://localhost:${info.port}`, 45 port: info.port, 46 }); 47 } 48 ); 49 50 // Start firehose subscription 51 ctx.firehose.start().catch((error) => { 52 logger.fatal("Failed to start firehose", { 53 error: error instanceof Error ? error.message : String(error), 54 }); 55 process.exit(1); 56 }); 57 58 // Graceful shutdown handler 59 const shutdown = async (signal: string) => { 60 logger.info("Shutdown initiated", { signal }); 61 62 try { 63 await destroyAppContext(ctx); 64 65 server.close(() => { 66 logger.info("Server closed"); 67 process.exit(0); 68 }); 69 70 setTimeout(() => { 71 logger.error("Forced shutdown after timeout"); 72 process.exit(1); 73 }, 10000); 74 } catch (error) { 75 logger.error("Error during shutdown", { 76 error: error instanceof Error ? error.message : String(error), 77 }); 78 process.exit(1); 79 } 80 }; 81 82 process.on("SIGTERM", () => shutdown("SIGTERM")); 83 process.on("SIGINT", () => shutdown("SIGINT")); 84} 85 86main().catch((error) => { 87 // Logger may not be initialized yet — fall back to structured stderr 88 process.stderr.write( 89 JSON.stringify({ 90 timestamp: new Date().toISOString(), 91 level: "fatal", 92 message: "Fatal error during startup", 93 service: "atbb-appview", 94 error: error?.message || String(error), 95 stack: error?.stack, 96 }) + "\n" 97 ); 98 process.exit(1); 99});