import { _post } from "lib/utils/post"; import { addRoute, createRouter, findRoute } from "rou3"; import { ServerContext, SessionContext } from "../session/type"; 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 newClientRouter = >( ...routers: T[] ) => { return new Proxy( {}, { get(target, api_name, receiver) { return (...args: any[]) => { for (const router of routers) { if (router[api_name as 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 = >( router: T ) => { const rou = createRouter<{ handler: { default: RouteFn }; opt?: RouteOption; }>(); for (const item of Object.values(router)) { try { addRoute(rou, undefined, item[0], { handler: (item as any)[1](), opt: item[2], }); } catch (e) {} } return { async handle(arg: ServerContext | SessionContext) { const { url, req } = arg; const found = findRoute(rou, undefined, url.pathname); if (found) { const route = found.data; if (route.handler instanceof Promise) { route.handler = await route.handler; } let result = null; if (route.opt && route.opt?.request_as === "raw") { result = await route.handler.default.bind(arg)(); } else { let params = []; try { params = await req.json(); } catch (e) {} result = await route.handler.default.bind(arg)(params); } if (typeof result === "object" && result instanceof Response) { return result; } return new Response(JSON.stringify(result)); } }, }; };