import type Database from "bun:sqlite"; import type { RuntimeMode } from "../shared/api"; import type { Logger } from "./logger"; import type { StaticAssets } from "./static"; import { createApiError, jsonResponse } from "./helpers"; import { withErrorHandler } from "./middleware"; import { handleMeta } from "./routes/meta"; import { serveStaticAsset } from "./static"; import { readAppVersion } from "./version"; export interface StartServerOptions { config: { host: string; port: number }; db: Database; logger: Logger; mode: RuntimeMode; staticAssets?: StaticAssets; version?: string; } export function startServer(options: StartServerOptions) { const { config, db, logger, mode, staticAssets, version } = options; const resolveVersion = (): Promise => { if (version) return Promise.resolve(version); return readAppVersion(); }; const server = Bun.serve({ fetch(req) { if (staticAssets) { return serveStaticAsset(new URL(req.url).pathname, staticAssets); } return new Response("Frontend is served by Vite dev server on :5173", { status: 404 }); }, hostname: config.host, port: config.port, routes: { "/api/*": () => jsonResponse(createApiError("API route not found", 404), { mode, status: 404 }), "/api/meta": { GET: withErrorHandler( async () => { const resolvedVersion = await resolveVersion(); return handleMeta(mode, resolvedVersion, logger); }, mode, logger, ), }, "/api/models": { GET: withErrorHandler( async (req) => { const { handleListModels } = await import("./routes/models/list"); return handleListModels(req, db, mode, logger); }, mode, logger, ), POST: withErrorHandler( async (req) => { const { handleCreateModel } = await import("./routes/models/create"); return handleCreateModel(req, db, mode, logger); }, mode, logger, ), }, "/api/models/:id": { DELETE: withErrorHandler( async (req) => { const { handleDeleteModel } = await import("./routes/models/delete"); return handleDeleteModel(req, db, mode, logger); }, mode, logger, ), GET: withErrorHandler( async (req) => { const { handleGetModel } = await import("./routes/models/get"); return handleGetModel(req, db, mode, logger); }, mode, logger, ), PATCH: withErrorHandler( async (req) => { const { handleUpdateModel } = await import("./routes/models/update"); return handleUpdateModel(req, db, mode, logger); }, mode, logger, ), }, "/api/models/test": { POST: withErrorHandler( async (req) => { const { handleTestModelConfig } = await import("./routes/models/test"); return handleTestModelConfig(req, db, mode, logger); }, mode, logger, ), }, "/api/projects": { GET: withErrorHandler( async (req) => { const { handleListProjects } = await import("./routes/projects/list"); return handleListProjects(req, db, mode, logger); }, mode, logger, ), POST: withErrorHandler( async (req) => { const { handleCreateProject } = await import("./routes/projects/create"); return handleCreateProject(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id": { DELETE: withErrorHandler( async (req) => { const { handleDeleteProject } = await import("./routes/projects/delete"); return handleDeleteProject(req, db, mode, logger); }, mode, logger, ), GET: withErrorHandler( async (req) => { const { handleGetProject } = await import("./routes/projects/get"); return handleGetProject(req, db, mode, logger); }, mode, logger, ), PATCH: withErrorHandler( async (req) => { const { handleUpdateProject } = await import("./routes/projects/update"); return handleUpdateProject(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/archive": { POST: withErrorHandler( async (req) => { const { handleArchiveProject } = await import("./routes/projects/archive"); return handleArchiveProject(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/chat": { POST: withErrorHandler( async (req) => { const { handleSendChat } = await import("./routes/chat/send"); return handleSendChat(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/conversations": { GET: withErrorHandler( async (req) => { const { handleListConversations } = await import("./routes/chat/list"); return handleListConversations(req, db, mode, logger); }, mode, logger, ), POST: withErrorHandler( async (req) => { const { handleCreateConversation } = await import("./routes/chat/create"); return handleCreateConversation(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/conversations/:cid": { DELETE: withErrorHandler( async (req) => { const { handleDeleteConversation } = await import("./routes/chat/delete"); return handleDeleteConversation(req, db, mode, logger); }, mode, logger, ), GET: withErrorHandler( async (req) => { const { handleGetConversation } = await import("./routes/chat/get"); return handleGetConversation(req, db, mode, logger); }, mode, logger, ), PATCH: withErrorHandler( async (req) => { const { handleUpdateConversation } = await import("./routes/chat/update"); return handleUpdateConversation(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/conversations/:cid/messages": { GET: withErrorHandler( async (req) => { const { handleListMessages } = await import("./routes/chat/messages"); return handleListMessages(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/materials": { GET: withErrorHandler( async (req) => { const { handleListMaterials } = await import("./routes/materials/list"); return handleListMaterials(req, db, mode, logger); }, mode, logger, ), POST: withErrorHandler( async (req) => { const { handleCreateMaterial } = await import("./routes/materials/create"); return handleCreateMaterial(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/materials/:mid": { DELETE: withErrorHandler( async (req) => { const { handleDeleteMaterial } = await import("./routes/materials/delete"); return handleDeleteMaterial(req, db, mode, logger); }, mode, logger, ), GET: withErrorHandler( async (req) => { const { handleGetMaterial } = await import("./routes/materials/get"); return handleGetMaterial(req, db, mode, logger); }, mode, logger, ), }, "/api/projects/:id/restore": { POST: withErrorHandler( async (req) => { const { handleRestoreProject } = await import("./routes/projects/restore"); return handleRestoreProject(req, db, mode, logger); }, mode, logger, ), }, "/api/providers": { GET: withErrorHandler( async (req) => { const { handleListProviders } = await import("./routes/providers/list"); return handleListProviders(req, db, mode, logger); }, mode, logger, ), POST: withErrorHandler( async (req) => { const { handleCreateProvider } = await import("./routes/providers/create"); return handleCreateProvider(req, db, mode, logger); }, mode, logger, ), }, "/api/providers/:id": { DELETE: withErrorHandler( async (req) => { const { handleDeleteProvider } = await import("./routes/providers/delete"); return handleDeleteProvider(req, db, mode, logger); }, mode, logger, ), GET: withErrorHandler( async (req) => { const { handleGetProvider } = await import("./routes/providers/get"); return handleGetProvider(req, db, mode, logger); }, mode, logger, ), PATCH: withErrorHandler( async (req) => { const { handleUpdateProvider } = await import("./routes/providers/update"); return handleUpdateProvider(req, db, mode, logger); }, mode, logger, ), }, "/api/providers/options": { GET: withErrorHandler( async () => { const { handleListProviderOptions } = await import("./routes/providers/options"); return handleListProviderOptions(db, mode, logger); }, mode, logger, ), }, "/api/providers/test": { POST: withErrorHandler( async (req) => { const { handleTestProviderConfig } = await import("./routes/providers/test"); return handleTestProviderConfig(req, db, mode, logger); }, mode, logger, ), }, }, }); logger.info({ host: config.host, port: config.port, url: server.url.toString() }, "服务启动"); return server; }