@vitejs/plugin-rsc
Version:
React Server Components (RSC) support for Vite.
91 lines (89 loc) • 2.35 kB
JavaScript
import { decode, encode } from "turbo-stream";
//#region src/utils/rpc.ts
const decodePlugins = [(type, ...rest) => {
switch (type) {
case "Request": {
const [method, url, headers, body] = rest;
return { value: new Request(url, {
body,
headers,
method,
duplex: body ? "half" : void 0
}) };
}
case "Response": {
const [status, statusText, headers, body] = rest;
return { value: new Response(body, {
headers,
status,
statusText
}) };
}
}
return false;
}];
const encodePlugins = [(obj) => {
if (obj instanceof Request) return [
"Request",
obj.method,
obj.url,
Array.from(obj.headers),
obj.body
];
if (obj instanceof Response) return [
"Response",
obj.status,
obj.statusText,
Array.from(obj.headers),
obj.body
];
return false;
}];
function createRpcServer(handlers) {
return async (request) => {
if (!request.body) throw new Error(`loadModuleDevProxy error: missing request body`);
const reqPayload = await decode(request.body.pipeThrough(new TextDecoderStream()), { plugins: decodePlugins });
const handler = handlers[reqPayload.method];
if (!handler) throw new Error(`loadModuleDevProxy error: unknown method ${reqPayload.method}`);
const resPayload = {
ok: true,
data: void 0
};
try {
resPayload.data = await handler(...reqPayload.args);
} catch (e) {
resPayload.ok = false;
resPayload.data = e;
}
return new Response(encode(resPayload, {
plugins: encodePlugins,
redactErrors: false
}));
};
}
function createRpcClient(options) {
async function callRpc(method, args) {
const body = encode({
method,
args
}, {
plugins: encodePlugins,
redactErrors: false
}).pipeThrough(new TextEncoderStream());
const res = await fetch(options.endpoint, {
method: "POST",
body,
duplex: "half"
});
if (!res.ok || !res.body) throw new Error(`loadModuleDevProxy error: ${res.status} ${res.statusText}`);
const resPayload = await decode(res.body.pipeThrough(new TextDecoderStream()), { plugins: decodePlugins });
if (!resPayload.ok) throw resPayload.data;
return resPayload.data;
}
return new Proxy({}, { get(_target, p, _receiver) {
if (typeof p !== "string" || p === "then") return;
return (...args) => callRpc(p, args);
} });
}
//#endregion
export { createRpcServer as n, createRpcClient as t };