r19
Version:
Simple remote procedure calls in TypeScript
121 lines (120 loc) • 3.88 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const node_buffer = require("node:buffer");
const msgpack = require("@msgpack/msgpack");
const isErrorLike = require("./lib/isErrorLike.cjs");
const isR19ErrorLike = require("./lib/isR19ErrorLike.cjs");
const replaceLeaves = require("./lib/replaceLeaves.cjs");
const R19Error = require("./R19Error.cjs");
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 = msgpack.decode(node_buffer.Buffer.from(args.body));
const procedure = findProcedure(args.procedures, clientArgs.procedurePath);
const headers = {
"Content-Type": "application/msgpack"
};
if (!procedure) {
const error = new R19Error.R19Error(`Invalid procedure name: ${clientArgs.procedurePath.join(".")}`, {
procedurePath: clientArgs.procedurePath,
procedureArgs: clientArgs.procedureArgs
});
const body = msgpack.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.replaceLeaves(clientArgs.procedureArgs, async (value) => {
if (value instanceof ArrayBuffer) {
return node_buffer.Buffer.from(value);
}
return value;
});
res = await procedure(...procedureArgs);
res = await replaceLeaves.replaceLeaves(res, async (value) => {
if (isErrorLike.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.R19Error("r19 does not support function return values.", {
procedurePath: clientArgs.procedurePath,
procedureArgs: clientArgs.procedureArgs
});
}
return value;
});
} catch (error) {
if (isErrorLike.isErrorLike(error)) {
const body = msgpack.encode({
error: isR19ErrorLike.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 = msgpack.encode({
data: res
}, { ignoreUndefined: true });
return {
body,
headers
};
} catch (error) {
if (error instanceof Error) {
const rpcError = new R19Error.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 = msgpack.encode(rpcError);
(_c = args.onError) == null ? void 0 : _c.call(args, { error, ...clientArgs });
return {
body,
headers,
statusCode: 500
};
}
throw error;
}
};
exports.handleRPCRequest = handleRPCRequest;
//# sourceMappingURL=handleRPCRequest.cjs.map