diff --git a/internal/content/content-ipc.ts b/internal/content/content-ipc.ts index 95a5945..3852278 100644 --- a/internal/content/content-ipc.ts +++ b/internal/content/content-ipc.ts @@ -1,25 +1,42 @@ +import { join } from "path"; import { g } from "utils/global"; -import type { PrasiContent } from "./types"; -import { ipcSend } from "./ipc/send"; import { staticFile } from "utils/static"; - +import { ipcSend } from "./ipc/send"; +import type { PrasiContent } from "./types"; export const prasi_content_ipc: PrasiContent = { prepare(site_id) {}, init() { return new Promise((done) => { if (g.mode === "site" && g.ipc) { - ipcSend({ type: "init" }); if (g.server) { console.log("restarting..."); process.exit(); } else { + ipcSend({ type: "init" }); process.on( "message", - async (msg: { type: "start"; path: { asset: string } }) => { + async ( + msg: + | { type: "start"; path: { backend: string; frontend: string } } + | { type: "reload-backend" } + | { type: "reload-frontend" } + ) => { if (g.mode === "site" && g.ipc) { if (msg.type === "start") { - g.ipc.asset = await staticFile(msg.path.asset); + g.ipc.frontend = await staticFile(msg.path.frontend); + g.ipc.backend_path = join(msg.path.backend, "server.js"); + delete require.cache[g.ipc.backend_path]; + g.ipc.backend = require(g.ipc.backend_path); done(); + } else if (msg.type === "reload-frontend") { + if (g.ipc.frontend) { + g.ipc.frontend.rescan({ immediately: true }); + } + } else if (msg.type === "reload-backend") { + if (g.ipc.backend_path) { + delete require.cache[g.ipc.backend_path]; + g.ipc.backend = require(g.ipc.backend_path); + } } } } @@ -34,7 +51,7 @@ export const prasi_content_ipc: PrasiContent = { } }, async staticFile(ctx) { - const asset = g.mode === "site" && g.ipc?.asset!; + const asset = g.mode === "site" && g.ipc?.frontend!; if (asset) { const response = asset.serve(ctx); if (response) { @@ -42,5 +59,24 @@ export const prasi_content_ipc: PrasiContent = { } } }, - async route(ctx) {}, + async route(ctx) { + if (g.mode === "site" && g.ipc) { + const server = g.ipc.backend?.server; + if (server) { + return server.http({ + url: ctx.url, + req: ctx.req, + server: ctx.server, + mode: "prod", + async handle(req, opt) { + return new Response("handle", { + status: 404, + }); + }, + index: { body: [], head: [], render: () => "" }, + prasi: {}, + }); + } + } + }, }; diff --git a/internal/utils/global.ts b/internal/utils/global.ts index 7610bae..15ad228 100644 --- a/internal/utils/global.ts +++ b/internal/utils/global.ts @@ -6,6 +6,7 @@ import type { PrasiSpawn, spawn } from "./spawn"; import type { prasi_content_ipc } from "../content/content-ipc"; import type { prasi_content_deploy } from "../content/content-deploy"; import type { StaticFile } from "./static"; +import type { PrasiServer } from "./server-typings"; if (!(globalThis as any).prasi) { (globalThis as any).prasi = {}; @@ -18,7 +19,9 @@ export const g = (globalThis as any).prasi as unknown as { mode: "site"; server: Server; ipc?: { - asset?: StaticFile; + frontend?: StaticFile; + backend_path?: string; + backend?: { server?: PrasiServer }; }; static_cache: any; prasi: typeof prasi_content_ipc & typeof prasi_content_deploy; diff --git a/internal/utils/server-typings.d.ts b/internal/utils/server-typings.d.ts new file mode 100644 index 0000000..b8410c3 --- /dev/null +++ b/internal/utils/server-typings.d.ts @@ -0,0 +1,23 @@ +export interface PrasiServer extends Record { + ws?: WebSocketHandler<{ url: string }>; + http: (arg: { + url: { raw: URL; pathname: string }; + req: Request; + server: Server; + mode: "dev" | "prod"; + handle: ( + req: Request, + opt?: { + rewrite?: (arg: { + body: Bun.BodyInit; + headers: Headers | any; + }) => Bun.BodyInit; + } + ) => Promise; + serveStatic?: any; + serveAPI?: any; + index: { head: string[]; body: string[]; render: () => string }; + prasi: { page_id?: string; params?: Record }; + }) => Promise; + init?: (arg: { port?: number }) => Promise; +} diff --git a/internal/utils/static.ts b/internal/utils/static.ts index 4e37219..bf9fe13 100644 --- a/internal/utils/static.ts +++ b/internal/utils/static.ts @@ -48,7 +48,7 @@ export const staticFile = async ( scanning: false, paths: new Set(), // rescan will be overwritten below. - async rescan(arg?: { immediatly?: boolean }) {}, + async rescan(arg?: { immediately?: boolean }) {}, exists(rpath: string, arg?: { prefix?: string; debug?: boolean }) { let pathname = rpath; if (arg?.prefix && pathname) { @@ -128,7 +128,7 @@ export const staticFile = async ( }; await scan(); - static_file.rescan = (arg?: { immediatly?: boolean }) => { + static_file.rescan = (arg?: { immediately?: boolean }) => { return new Promise((resolve) => { clearTimeout(internal.rescan_timeout); internal.rescan_timeout = setTimeout( @@ -136,7 +136,7 @@ export const staticFile = async ( await scan(); resolve(); }, - arg?.immediatly ? 0 : 300 + arg?.immediately ? 0 : 300 ); }); };