UNPKG

r19

Version:

Simple remote procedure calls in TypeScript

121 lines (120 loc) 3.62 kB
import { Buffer } from "node:buffer"; import { decode, encode } from "@msgpack/msgpack"; import { isErrorLike } from "./lib/isErrorLike.js"; import { isR19ErrorLike } from "./lib/isR19ErrorLike.js"; import { replaceLeaves } from "./lib/replaceLeaves.js"; import { R19Error } from "./R19Error.js"; const findProcedure = (procedures, path) => { path = [...path]; let proceduresPointer = procedures; while (path.length > 0) { const pathSegment = path.shift(); if (pathSegment) { proceduresPointer = proceduresPointer[pathSegment]; if (typeof proceduresPointer === "function") { return proceduresPointer; } else if (proceduresPointer === void 0) { return; } } } }; const handleRPCRequest = async (args) => { var _a, _b, _c; if (!args.body) { throw new Error("Invalid request body. Only requests from an r19 client are accepted."); } const clientArgs = decode(Buffer.from(args.body)); const procedure = findProcedure(args.procedures, clientArgs.procedurePath); const headers = { "Content-Type": "application/msgpack" }; if (!procedure) { const error = new R19Error(`Invalid procedure name: ${clientArgs.procedurePath.join(".")}`, { procedurePath: clientArgs.procedurePath, procedureArgs: clientArgs.procedureArgs }); const body = encode({ error }, { ignoreUndefined: true }); (_a = args.onError) == null ? void 0 : _a.call(args, { error, ...clientArgs }); return { body, headers, statusCode: 500 }; } let res; try { const procedureArgs = await replaceLeaves(clientArgs.procedureArgs, async (value) => { if (value instanceof ArrayBuffer) { return Buffer.from(value); } return value; }); res = await procedure(...procedureArgs); res = await replaceLeaves(res, async (value) => { if (isErrorLike(value)) { return { name: value.name, message: value.message, stack: process.env.NODE_ENV === "development" ? value.stack : void 0 }; } if (typeof value === "function") { throw new R19Error("r19 does not support function return values.", { procedurePath: clientArgs.procedurePath, procedureArgs: clientArgs.procedureArgs }); } return value; }); } catch (error) { if (isErrorLike(error)) { const body = encode({ error: isR19ErrorLike(error) ? error : { name: error.name, message: error.message, stack: process.env.NODE_ENV === "development" ? error.stack : void 0 } }, { ignoreUndefined: true }); (_b = args.onError) == null ? void 0 : _b.call(args, { error, ...clientArgs }); return { body, headers, statusCode: 500 }; } throw error; } try { const body = encode({ data: res }, { ignoreUndefined: true }); return { body, headers }; } catch (error) { if (error instanceof Error) { const rpcError = new R19Error("Unable to serialize server response. Check the server log for details.", { procedurePath: clientArgs.procedurePath, procedureArgs: clientArgs.procedureArgs, cause: error }); console.error(rpcError); const body = encode(rpcError); (_c = args.onError) == null ? void 0 : _c.call(args, { error, ...clientArgs }); return { body, headers, statusCode: 500 }; } throw error; } }; export { handleRPCRequest }; //# sourceMappingURL=handleRPCRequest.js.map