From 4396c3cd6e9b20f8aef12a1591bab01df53074dc Mon Sep 17 00:00:00 2001 From: Rizky Date: Fri, 9 Feb 2024 13:31:03 +0700 Subject: [PATCH] wip fix --- app/srv/global.ts | 6 ++++ app/srv/init.ts | 31 ++++++++++++++-- app/srv/ws/sync/actions/code_action.ts | 2 +- app/srv/ws/sync/editor/code/build-code.ts | 38 ++++++++++++++++++-- app/srv/ws/sync/editor/code/prep-code.ts | 2 +- app/srv/ws/sync/editor/code/util-code.ts | 14 ++++++++ pkgs/core/index.ts | 20 +++++------ pkgs/core/server/create.ts | 44 +++++++++++++---------- pkgs/core/server/serve-ws.ts | 13 +++++++ pkgs/core/utils/global.ts | 10 +++++- 10 files changed, 145 insertions(+), 35 deletions(-) diff --git a/app/srv/global.ts b/app/srv/global.ts index 4eb4e56e..5c77ae7e 100644 --- a/app/srv/global.ts +++ b/app/srv/global.ts @@ -1,8 +1,12 @@ +import { Server } from "bun"; import { site, user } from "dbgen"; import { ExecaChildProcess } from "execa"; +import { g } from "utils/global"; declare global { + //@ts-ignore const Y: typeof Y; + //@ts-ignore const syncronize: typeof Y.syncronize; } @@ -20,6 +24,8 @@ export const glb = global as unknown as { >; running: Record; }; + server_hook?: typeof g.server_hook; + ws_hook?: typeof g.ws_hook; npm: { page: Record; site: Record; diff --git a/app/srv/init.ts b/app/srv/init.ts index 7a7ae211..b0fcaefa 100644 --- a/app/srv/init.ts +++ b/app/srv/init.ts @@ -1,5 +1,32 @@ +import { existsAsync } from "fs-jetpack"; import { glb } from "./global"; +import { code, server } from "./ws/sync/editor/code/util-code"; -export const initSrv = async () => { - glb.npm = { page: {}, site: {} }; +glb.npm = { page: {}, site: {} }; + +glb.server_hook = async (arg) => { + const url = arg.url; + if (url.pathname.startsWith("/prod")) { + const arr = url.pathname.split("/"); + const site_id = arr[2]; + + if (typeof server[site_id] === "undefined") { + const server_src_path = code.path(site_id, "server", "build", "index.js"); + server[site_id] = null; + if (await existsAsync(server_src_path)) { + const svr = require(server_src_path); + if (svr && svr.server) { + server[site_id] = svr.server; + } + } + } + + if (server[site_id]) { + try { + return await server[site_id]?.http(arg); + } catch (e) {} + } + } + + if (arg.handle) return await arg.handle(arg.req); }; diff --git a/app/srv/ws/sync/actions/code_action.ts b/app/srv/ws/sync/actions/code_action.ts index a0354f29..2fbe825b 100644 --- a/app/srv/ws/sync/actions/code_action.ts +++ b/app/srv/ws/sync/actions/code_action.ts @@ -104,7 +104,7 @@ export const code_action: SAction["code"]["action"] = async function ( ); await Bun.write( Bun.file(path.join(dir, "global.d.ts")), - ` + `\ import prisma from "./prisma"; import type * as SRVAPI from "gen/srv/api/srv"; diff --git a/app/srv/ws/sync/editor/code/build-code.ts b/app/srv/ws/sync/editor/code/build-code.ts index 91a09201..41c70f47 100644 --- a/app/srv/ws/sync/editor/code/build-code.ts +++ b/app/srv/ws/sync/editor/code/build-code.ts @@ -5,7 +5,7 @@ import { dirAsync, existsAsync, removeAsync, writeAsync } from "fs-jetpack"; import { DCode } from "../../../../../web/src/utils/types/root"; import { readDirectoryRecursively } from "../../../../api/site-export"; import { docs } from "../../entity/docs"; -import { CodeMode, code } from "./util-code"; +import { code, server } from "./util-code"; export const codeBuild = async (id_site: any) => { const src_path = code.path(id_site, "site", "src"); @@ -17,7 +17,26 @@ export const codeBuild = async (id_site: any) => { if (!code.esbuild[id_site].server) { const server_main = code.path(id_site, "site", "src", "server.ts"); if (!(await existsAsync(server_main))) { - await writeAsync(server_main, ""); + await writeAsync( + server_main, + `\ +import { Server, WebSocketHandler } from "bun"; + +export const server: { + ws?: WebSocketHandler<{ url: string }>; + http: (arg: { + url: URL; + req: Request; + server: Server; + handle: (req: Request) => Promise; + }) => Promise; +} = { + async http({ req, handle, url, server }) { + return await handle(req); + }, +}; +` + ); const bun_types = Bun.spawn({ cmd: ["npm", "i", "-D", "@types/bun"], cwd: code.path(id_site, "site", "src"), @@ -53,6 +72,21 @@ export const codeBuild = async (id_site: any) => { type: "cjs", }, }), + { + name: "prasi", + setup(setup) { + setup.onEnd(async (res) => { + const server_src_path = code.path(id_site, "server", "build", "index.js"); + server[id_site] = null; + if (await existsAsync(server_src_path)) { + const svr = require(server_src_path); + if (svr && svr.server) { + server[id_site] = svr.server; + } + } + }); + }, + }, ], }); const esbuild = code.esbuild[id_site].server; diff --git a/app/srv/ws/sync/editor/code/prep-code.ts b/app/srv/ws/sync/editor/code/prep-code.ts index 92b0afd2..49d50495 100644 --- a/app/srv/ws/sync/editor/code/prep-code.ts +++ b/app/srv/ws/sync/editor/code/prep-code.ts @@ -33,7 +33,7 @@ export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => { if (dcode) { if (!dcode.build[mode]) { const build_dir = code.path(id_site, mode, "build"); - await codeBuild(id_site, mode); + await codeBuild(id_site); dcode.build[mode] = codeLoad(id_site, build_dir); const doc = dcode.build[mode] as Doc; if (doc) { diff --git a/app/srv/ws/sync/editor/code/util-code.ts b/app/srv/ws/sync/editor/code/util-code.ts index dc2fcbbc..25029f91 100644 --- a/app/srv/ws/sync/editor/code/util-code.ts +++ b/app/srv/ws/sync/editor/code/util-code.ts @@ -1,9 +1,22 @@ +import { Server, WebSocketHandler } from "bun"; import { dir } from "dir"; import { BuildContext } from "esbuild"; import { dirAsync, exists, existsAsync, writeAsync } from "fs-jetpack"; import { dirname } from "path"; export type CodeMode = "site" | "server"; + +type PrasiServer = { + ws?: WebSocketHandler<{ url: string }>; + http: (arg: { + url: URL; + req: Request; + server: Server; + handle: (req: Request) => Promise; + }) => Promise; +}; +export const server = {} as Record; + export const code = { path(id_site: string, mode: CodeMode, type: "src" | "build", path?: string) { let file_path = ""; @@ -15,6 +28,7 @@ export const code = { package_deps: (path: string) => { const file = Bun.file(path); }, + server: {} as Record, esbuild: {} as Record>, prep(id_site: string, mode: CodeMode) { if (exists(dir.data(""))) { diff --git a/pkgs/core/index.ts b/pkgs/core/index.ts index 81dee2ca..bd2a281b 100644 --- a/pkgs/core/index.ts +++ b/pkgs/core/index.ts @@ -1,23 +1,23 @@ +import { createId } from "@paralleldrive/cuid2"; +import { dir } from "dir"; +import { writeAsync } from "fs-jetpack"; import { parcelBuild } from "utils/parcel"; +import { syncActionDefinition } from "utils/sync-def"; +import { snapshot } from "../../app/srv/ws/sync/entity/snapshot"; +import { user } from "../../app/srv/ws/sync/entity/user"; +import { prepareApiRoutes } from "./server/api/api-scan"; +import { watchApiRoutes } from "./server/api/api-watch"; import { prepareAPITypes } from "./server/api/prep-api-ts"; import { startDevWatcher } from "./utils/dev-watcher"; import { ensureNotRunning } from "./utils/ensure"; import { g } from "./utils/global"; import { createLogger } from "./utils/logger"; import { preparePrisma } from "./utils/prisma"; -import { syncActionDefinition } from "utils/sync-def"; -import { user } from "../../app/srv/ws/sync/entity/user"; -import { snapshot } from "../../app/srv/ws/sync/entity/snapshot"; -import { initSrv } from "../../app/srv/init"; -import { createId } from "@paralleldrive/cuid2"; -import { prepareApiRoutes } from "./server/api/api-scan"; -import { writeAsync } from "fs-jetpack"; -import { dir } from "dir"; -import { watchApiRoutes } from "./server/api/api-watch"; // import "../docker-prep"; g.status = "init"; + await writeAsync( dir.path("app/web/timestamp.ts"), `export const version = "${createId().substring(0, 7)}";` @@ -57,10 +57,10 @@ if (!db) { }); } } +await import("../../app/srv/init"); await prepareApiRoutes(); if (!g.apiPrepared) { - await initSrv(); await syncActionDefinition(); g.log.info("WS Action defined"); await prepareAPITypes(); diff --git a/pkgs/core/server/create.ts b/pkgs/core/server/create.ts index a09414bc..2fd8307d 100644 --- a/pkgs/core/server/create.ts +++ b/pkgs/core/server/create.ts @@ -29,29 +29,37 @@ export const createServer = async () => { async fetch(req, server) { const url = new URL(req.url); - if (wsHandler[url.pathname]) { - if ( - server.upgrade(req, { - data: { - url: new URL(req.url), - }, - }) - ) { - return; + const handle = async (req: Request) => { + if (wsHandler[url.pathname]) { + if ( + server.upgrade(req, { + data: { + url: new URL(req.url), + }, + }) + ) { + return; + } + return new Response("Upgrade failed :(", { status: 500 }); + } + + if (serveStatic.exists(url)) { + return serveStatic.serve(url); + } + + const api_response = await serveAPI.serve(url, req); + if (api_response) { + return api_response; } - return new Response("Upgrade failed :(", { status: 500 }); - } - if (serveStatic.exists(url)) { return serveStatic.serve(url); - } + }; - const api_response = await serveAPI.serve(url, req); - if (api_response) { - return api_response; + if (g.server_hook) { + return await g.server_hook({ url, req, server, handle }); + } else { + return await handle(req); } - - return serveStatic.serve(url); }, }); diff --git a/pkgs/core/server/serve-ws.ts b/pkgs/core/server/serve-ws.ts index 8de6790c..c988f83a 100644 --- a/pkgs/core/server/serve-ws.ts +++ b/pkgs/core/server/serve-ws.ts @@ -1,5 +1,6 @@ import { WebSocketHandler } from "bun"; import { WSData } from "./create"; +import { g } from "utils/global"; export const serveWS: ( wsHandler: Record> @@ -8,9 +9,15 @@ export const serveWS: ( maxPayloadLength: 9999999, closeOnBackpressureLimit: true, drain(ws) { + if (g.ws_hook && g.ws_hook.drain) { + return g.ws_hook.drain(ws); + } // console.log("Backpressure relieved..."); }, close(ws, code, reason) { + if (g.ws_hook && g.ws_hook.close) { + g.ws_hook.close(ws, code, reason); + } const pathname = ws.data.url.pathname; if (wsHandler[pathname]) { const close = wsHandler[pathname].close; @@ -20,6 +27,9 @@ export const serveWS: ( } }, message(ws, message) { + if (g.ws_hook && g.ws_hook.message) { + g.ws_hook.message(ws, message); + } const pathname = ws.data.url.pathname; if (wsHandler[pathname]) { const msg = wsHandler[pathname].message; @@ -29,6 +39,9 @@ export const serveWS: ( } }, open(ws) { + if (g.ws_hook && g.ws_hook.open) { + g.ws_hook.open(ws); + } const pathname = ws.data.url.pathname; if (wsHandler[pathname]) { const open = wsHandler[pathname].open; diff --git a/pkgs/core/utils/global.ts b/pkgs/core/utils/global.ts index 1479e10d..82081953 100644 --- a/pkgs/core/utils/global.ts +++ b/pkgs/core/utils/global.ts @@ -1,9 +1,10 @@ -import { Server, Subprocess } from "bun"; +import { Server, Subprocess, WebSocketHandler } from "bun"; import { Logger } from "pino"; import { RadixRouter } from "radix3"; import { syncronize } from "y-pojo"; import type * as Y from "yjs"; import { PrismaClient } from "../../../app/db/db"; +import { WSData } from "../server/create"; type SingleRoute = { url: string; @@ -14,6 +15,13 @@ type SingleRoute = { export const g = global as unknown as { status: "init" | "ready"; + server_hook?: (arg: { + url: URL; + req: Request; + server: Server; + handle: (req: Request) => Promise; + }) => Promise; + ws_hook?: WebSocketHandler; _db: PrismaClient; dburl: string; mode: "dev" | "prod";