r19
Version:
Simple remote procedure calls in TypeScript
82 lines (81 loc) • 2.54 kB
JavaScript
import { encode, decode } 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 createArbitrarilyNestedFunction = (handler, path = []) => {
return new Proxy(() => void 0, {
apply(_target, _this, args) {
return handler(path, args);
},
get(_target, property) {
return createArbitrarilyNestedFunction(handler, [
...path,
property.toString()
]);
}
});
};
const createRPCClient = (args) => {
const resolvedFetch = args.fetch || globalThis.fetch.bind(globalThis);
return createArbitrarilyNestedFunction(async (procedurePath, procedureArgs) => {
const preparedProcedureArgs = await replaceLeaves(procedureArgs, async (value) => {
if (value instanceof Blob) {
return new Uint8Array(await value.arrayBuffer());
}
if (typeof value === "function") {
throw new R19Error("r19 does not support function arguments.", {
procedurePath,
procedureArgs
});
}
return value;
});
const body = encode({
procedurePath,
procedureArgs: preparedProcedureArgs
}, { ignoreUndefined: true });
const res = await resolvedFetch(args.serverURL, {
method: "POST",
body,
headers: {
"Content-Type": "application/msgpack"
}
});
const arrayBuffer = await res.arrayBuffer();
const resObject = decode(new Uint8Array(arrayBuffer));
if ("error" in resObject) {
const resError = resObject.error;
if (isR19ErrorLike(resError)) {
const error = new R19Error(resError.message, {
procedurePath,
procedureArgs
});
error.stack = resError.stack;
throw error;
} else if (isErrorLike(resError)) {
const error = new Error(resError.message);
error.name = resError.name;
error.stack = resError.stack;
throw error;
} else {
throw new R19Error("An unexpected response was received from the RPC server.", {
procedurePath,
procedureArgs,
cause: resObject
});
}
} else {
return replaceLeaves(resObject.data, async (value) => {
if (value instanceof Uint8Array) {
return new Blob([value]);
}
return value;
});
}
});
};
export {
createRPCClient
};
//# sourceMappingURL=createRPCClient.js.map