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 atb-52-css-token-extraction 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});