import { _post } from "lib/utils/post"; import { addRoute, createRouter, findRoute } from "rou3"; export type ServerArg = { req: Request; handle: (req: Request) => Promise; mode: "dev" | "prod"; url: { raw: URL; pathname: string; }; }; type RouteFn = (...arg: any[]) => Promise; type SingleRoute = [string, () => Promise<{ default: RouteFn }>]; type SingleRouteWithOption = [ string, () => Promise<{ default: RouteFn }>, RouteOption ]; type RouteOption = { request_as?: "json" | "raw"; response_as?: "json" | "raw"; }; export const newServerRouter = < T extends Record >( arg: T ) => { return arg; }; export const createClientForServer = >( router: T ) => { return new Proxy( {}, { get(target, api_name, receiver) { return (...args: any[]) => { const [url, _, opt] = router[api_name as any]; if (opt && opt.response_as) return _post(url, args, { response_as: opt.response_as }); return _post(url, args); }; }, } ) as { [K in keyof T]: Awaited>["default"]; }; }; export const useServerRouter = async >( router: T ) => { const rou = createRouter<{ handler: { default: RouteFn }; opt?: RouteOption; }>(); for (const item of Object.values(router)) { try { addRoute(rou, undefined, item[0], { handler: await (item as any)[1](), opt: item[2], }); } catch (e) {} } return { async handle(arg: ServerArg) { const { url, req } = arg; const found = findRoute(rou, undefined, url.pathname); if (found) { const route = found.data; let result = null; if (!route.opt || route.opt?.request_as === "raw") { result = await route.handler.default(); } else { const params = await req.json(); result = await route.handler.default(...params); } if (result) return result; else return new Response(JSON.stringify(result)); } return await arg.handle(arg.req); }, }; };