import type { Server, WebSocketHandler } from "bun"; import { existsAsync } from "fs-jetpack"; import _fs from "node:fs/promises"; import { g } from "utils/global"; import { waitUntil } from "web-utils"; import { WSData } from "../../../../../../pkgs/core/server/create"; import { prodIndex } from "../../../../util/prod-index"; import { code } from "../../code/code"; import "./server-runtime"; const serverMain = () => ({ handler: {} as Record, init_timeout: null as any, ws(action: keyof WebSocketHandler, ...arg: any[]) { const id = arg[0].data.site_id; if (this.handler[id]) { const handler = this.handler[id].ws; if (handler) { const fn = handler[action] as any; if (typeof fn === "function") { return fn(...arg); } } } }, init(site_id: string) { clearTimeout(this.init_timeout); this.init_timeout = setTimeout(async () => { try { const server_src_path = code.path( site_id, "server", "build", "index.js" ); delete require.cache[server_src_path]; const svr = require(server_src_path); if (svr && typeof svr.server === "object") { this.handler[site_id] = svr.server; this.handler[site_id].site_id = site_id; if (typeof svr.server.init === "function") { svr.server.init({}); } Bun.write( Bun.file(code.path(site_id, "site", "src", "server.log")), "" ); } } catch (e) { console.log(`Failed to init server ${site_id}\n`, e); } }, 10); }, async http( site_id: string, arg: Parameters>[0] ) { if (arg.url.pathname.endsWith("main.js")) { code.init(site_id, "init http"); } if (typeof this.handler[site_id] === "undefined") { if ( await existsAsync(code.path(site_id, "server", "build", "index.js")) ) { this.init(site_id); await waitUntil(200); } } const handler = this.handler[site_id]; if (handler) { if (!handler.site_id) handler.site_id = site_id; try { if ( handler.ws && arg.req.headers.get("connection")?.toLowerCase() === "upgrade" && !arg.wsHandler[arg.url.pathname] ) { if ( arg.server.upgrade(arg.req, { data: { url: new URL(arg.req.url), site_id, }, }) ) { return; } return new Response("Upgrade failed :(", { status: 500 }); } const pathname = `/${arg.url.pathname.split("/").slice(3).join("/")}`; return await handler.http({ ...arg, url: { pathname, raw: arg.url, }, mode: "dev", index: prodIndex(site_id, arg.prasi), }); } catch (e: any) { _fs.appendFile( code.path(site_id, "site", "src", "server.log"), e.message + "\n" ); } } }, }); type PrasiServer = { site_id?: string; ws?: WebSocketHandler<{ url: string }>; http: (arg: { url: { raw: URL; pathname: string }; req: Request; server: Server; handle: (req: Request) => Promise; mode: "dev" | "prod"; index: { head: string[]; body: string[]; render: () => string }; prasi: { page_id?: string; params?: Record }; }) => Promise; init?: (arg: { port?: number }) => Promise; }; const glb = global as unknown as { _server: ReturnType; }; glb._server = serverMain(); export const server = glb._server;