Skip to content

Commit

Permalink
fix: reply encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Mar 13, 2023
1 parent 93fc52d commit d5d12c9
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 11 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
"dependencies": {
"@swc/core": "1.3.39",
"@vitejs/plugin-react": "^3.1.0",
"busboy": "^1.6.0",
"vite": "^4.1.4"
},
"devDependencies": {
"@swc/cli": "^0.1.62",
"@types/babel__core": "^7.20.0",
"@types/busboy": "^1.5.0",
"@types/node": "^18.15.0",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
Expand Down
22 changes: 22 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ReactNode } from "react";
import RSDWClient from "react-server-dom-webpack/client";

const { createFromFetch } = RSDWClient;
const { createFromFetch, encodeReply } = RSDWClient;

export function serve<Props>(rscId: string, render: (ele: ReactNode) => void) {
return async (props: Props) => {
Expand All @@ -10,7 +10,8 @@ export function serve<Props>(rscId: string, render: (ele: ReactNode) => void) {
searchParams.set("rsc_id", rscId);
searchParams.set("props", serializedProps);
const options = {
callServer(rsfId: string, args: unknown[]) {
async callServer(rsfId: string, args: unknown[]) {
const isMutating = !!mutationMode;
const searchParams = new URLSearchParams();
searchParams.set("rsf_id", rsfId);
if (isMutating) {
Expand All @@ -19,7 +20,7 @@ export function serve<Props>(rscId: string, render: (ele: ReactNode) => void) {
}
const response = fetch(`/?${searchParams}`, {
method: "POST",
body: JSON.stringify(args),
body: await encodeReply(args),
});
const data = createFromFetch(response, options);
if (isMutating) {
Expand All @@ -38,13 +39,13 @@ export function serve<Props>(rscId: string, render: (ele: ReactNode) => void) {
};
}

let isMutating = 0;
let mutationMode = 0;

export function mutate<Fn extends (...args: any[]) => any>(fn: Fn): Fn {
return ((...args: unknown[]) => {
++isMutating;
++mutationMode;
const result = fn(...args);
--isMutating;
--mutationMode;
return result;
}) as Fn;
}
22 changes: 17 additions & 5 deletions src/middleware/rscDev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import url from "node:url";
import * as swc from "@swc/core";
import RSDWRegister from "react-server-dom-webpack/node-register";
import RSDWServer from "react-server-dom-webpack/server";
import busboy from "busboy";

import type { MiddlewareCreator } from "./common.ts";

const { renderToPipeableStream } = RSDWServer;
const { renderToPipeableStream, decodeReply, decodeReplyFromBusboy } =
RSDWServer;

// TODO we would like a native solution without hacks
// https://nodejs.org/api/esm.html#loaders
Expand Down Expand Up @@ -80,11 +82,21 @@ const rscDefault: MiddlewareCreator = (config) => {
if (typeof rsfId === "string") {
const [filePath, name] = rsfId.split("#");
const fname = path.join(dir, filePath!);
let body = "";
for await (const chunk of req) {
body += chunk;
let args: unknown[] = [];
if (req.headers["content-type"]?.startsWith("multipart/form-data")) {
const bb = busboy({ headers: req.headers });
const reply = decodeReplyFromBusboy(bb);
req.pipe(bb);
args = await reply;
} else {
let body = "";
for await (const chunk of req) {
body += chunk;
}
if (body) {
args = await decodeReply(body);
}
}
const args = body ? JSON.parse(body) : [];
// TODO can we use node:vm?
const mod = require(fname);
const data = await (mod[name!] || mod)(...args);
Expand Down

0 comments on commit d5d12c9

Please sign in to comment.