| 58 | * static files from the built React SPA at `web/dist/`. |
| 59 | */ |
| 60 | export class HonoServer { |
| 61 | private _app: AppType; |
| 62 | private _server: Server<undefined> | undefined; |
| 63 | private _logger: Logger; |
| 64 | |
| 65 | constructor() { |
| 66 | this._logger = createLogger("hono-server"); |
| 67 | this._app = createApp(); |
| 68 | this._setupStaticServing(); |
| 69 | } |
| 70 | |
| 71 | get app(): AppType { |
| 72 | return this._app; |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Start listening on the configured host and port. |
| 77 | * |
| 78 | * Uses `AGENTARA_SERVICE_PORT` (default 1984) and |
| 79 | * `AGENTARA_SERVICE_HOST` (default 0.0.0.0). |
| 80 | */ |
| 81 | async start(): Promise<void> { |
| 82 | const port = parseInt(Bun.env.AGENTARA_SERVICE_PORT ?? "1984", 10); |
| 83 | const hostname = Bun.env.AGENTARA_SERVICE_HOST ?? "0.0.0.0"; |
| 84 | |
| 85 | this._server = Bun.serve({ |
| 86 | fetch: this._app.fetch, |
| 87 | port, |
| 88 | hostname, |
| 89 | }); |
| 90 | |
| 91 | this._logger.info( |
| 92 | "HTTP server is running on http://" + |
| 93 | hostname + |
| 94 | (port === 80 ? "" : ":" + port), |
| 95 | ); |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Gracefully shut down the server. |
| 100 | */ |
| 101 | async stop(): Promise<void> { |
| 102 | if (this._server) { |
| 103 | await this._server.stop(true); |
| 104 | this._logger.info("HTTP server stopped"); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | private _setupStaticServing(): void { |
| 109 | if (Bun.env.NODE_ENV === "production") { |
| 110 | const webRoot = join(process.cwd(), "web", "dist"); |
| 111 | if (existsSync(webRoot)) { |
| 112 | this._app.use("/*", serveStatic({ root: webRoot })); |
| 113 | // SPA fallback: serve index.html for non-API, non-asset routes |
| 114 | this._app.get("*", serveStatic({ path: join(webRoot, "index.html") })); |
| 115 | } |
| 116 | } |
| 117 | } |
nothing calls this directly
no outgoing calls
no test coverage detected