diff --git a/app/srv/init.ts b/app/srv/init.ts index ce891aed..d3aed0a9 100644 --- a/app/srv/init.ts +++ b/app/srv/init.ts @@ -2,13 +2,34 @@ import { glb } from "./global"; import { server } from "./ws/sync/editor/code/server-main"; glb.npm = { page: {}, site: {} }; +glb.ws_hook = { + ping(ws, data) { + server.ws("ping", ws, data); + }, + pong(ws, data) { + server.ws("pong", ws, data); + }, + drain(ws) { + server.ws("drain", ws); + }, + close(ws, code, reason) { + server.ws("close", ws, code, reason); + }, + message(ws, message) { + server.ws("message", ws, message); + }, + open(ws) { + server.ws("open", ws); + }, +}; + glb.server_hook = async (arg) => { const url = arg.url; if (url.pathname.startsWith("/prod")) { const arr = url.pathname.split("/"); const site_id = arr[2]; - return await server.serve(site_id, arg); + return await server.http(site_id, arg); } if (arg.handle) return await arg.handle(arg.req); diff --git a/app/srv/ws/sync/editor/code/build-code.ts b/app/srv/ws/sync/editor/code/build-code.ts index eb786119..d17c1e9b 100644 --- a/app/srv/ws/sync/editor/code/build-code.ts +++ b/app/srv/ws/sync/editor/code/build-code.ts @@ -93,6 +93,7 @@ if (typeof global.server_hook === "function") { name: "prasi", setup(setup) { setup.onEnd((res) => { + console.log("en bul"); server.init(id_site); }); }, diff --git a/app/srv/ws/sync/editor/code/server-main.ts b/app/srv/ws/sync/editor/code/server-main.ts index c310afe9..8b3d9fda 100644 --- a/app/srv/ws/sync/editor/code/server-main.ts +++ b/app/srv/ws/sync/editor/code/server-main.ts @@ -1,7 +1,101 @@ -import type { Server, WebSocketHandler } from "bun"; +import type { Server, WebSocketHandler, ServerWebSocket } from "bun"; +import { existsAsync } from "fs-jetpack"; import _fs from "node:fs/promises"; import { g } from "utils/global"; +import { waitUntil } from "web-utils"; import { code } from "./util-code"; +import { WSData } from "../../../../../../pkgs/core/server/create"; +import { codeBuild } from "./build-code"; + +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(() => { + console.log("initing", site_id); + 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 && svr.server) { + this.handler[site_id] = svr.server; + } + + Bun.write( + Bun.file(code.path(site_id, "site", "src", "server.log")), + "" + ); + } catch (e) { + console.log(`Failed to init server ${site_id}`); + } + }, 100); + }, + async http( + site_id: string, + arg: Parameters>[0] + ) { + if (!code.esbuild[site_id]) { + await codeBuild(site_id); + } + 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) { + 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 }); + } + + return await handler.http(arg); + } catch (e: any) { + _fs.appendFile( + code.path(site_id, "site", "src", "server.log"), + e.message + "\n" + ); + } + } + }, +}); type PrasiServer = { ws?: WebSocketHandler<{ url: string }>; @@ -13,54 +107,10 @@ type PrasiServer = { }) => Promise; }; -if (!g._server) { - g._server = { - handler: {} as Record, - init_timeout: null as any, - init(site_id: string) { - clearTimeout(this.init_timeout); - this.init_timeout = setTimeout(() => { - console.log("server init", site_id); - 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 && svr.server) { - this.handler[site_id] = svr.server; - } - - Bun.write( - Bun.file(code.path(site_id, "site", "src", "server.log")), - "" - ); - } catch (e) { - console.log(`Failed to init server ${site_id}`); - } - }, 300); - }, - async serve( - site_id: string, - arg: Parameters>[0] - ) { - const handler = this.handler[site_id]; - console.log(this.handler); - - if (handler) { - try { - return await handler.http(arg); - } catch (e: any) { - _fs.appendFile( - code.path(site_id, "site", "src", "server.log"), - e.message + "\n" - ); - } - } - }, - }; +const glb = global as unknown as { + _server: ReturnType; +}; +if (!glb._server) { + glb._server = serverMain(); } -export const server = g._server; +export const server = glb._server; diff --git a/pkgs/core/server/create.ts b/pkgs/core/server/create.ts index 2fd8307d..a5cb1b57 100644 --- a/pkgs/core/server/create.ts +++ b/pkgs/core/server/create.ts @@ -28,7 +28,6 @@ export const createServer = async () => { websocket: await serveWS(wsHandler), async fetch(req, server) { const url = new URL(req.url); - const handle = async (req: Request) => { if (wsHandler[url.pathname]) { if ( @@ -56,7 +55,7 @@ export const createServer = async () => { }; if (g.server_hook) { - return await g.server_hook({ url, req, server, handle }); + return await g.server_hook({ url, req, server, handle, wsHandler }); } else { return await handle(req); } diff --git a/pkgs/core/utils/global.ts b/pkgs/core/utils/global.ts index f57d4a27..d506b18c 100644 --- a/pkgs/core/utils/global.ts +++ b/pkgs/core/utils/global.ts @@ -15,12 +15,12 @@ type SingleRoute = { export const g = global as unknown as { status: "init" | "ready"; - _server: any; server_hook?: (arg: { url: URL; req: Request; server: Server; handle: (req: Request) => Promise; + wsHandler: Record>; }) => Promise; ws_hook?: WebSocketHandler; _db: PrismaClient;