From 466ec99980120b316fa8d31100d54fab298f9989 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:00:45 +0900 Subject: [PATCH 01/14] feat(plugin-rsc): provide types for RSC API options Replace `object` and `unknown` option types with proper TypeScript interfaces for the re-exported react-server-dom-webpack API, giving downstream users IDE support and type safety. Closes #1153 Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/plugin-rsc/src/react/browser.ts | 12 ++++--- packages/plugin-rsc/src/react/rsc.ts | 14 +++++--- packages/plugin-rsc/src/react/ssr.ts | 3 +- packages/plugin-rsc/src/types/index.ts | 41 ++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/packages/plugin-rsc/src/react/browser.ts b/packages/plugin-rsc/src/react/browser.ts index 3cf05a3f5..880ffcfcc 100644 --- a/packages/plugin-rsc/src/react/browser.ts +++ b/packages/plugin-rsc/src/react/browser.ts @@ -1,12 +1,16 @@ // @ts-ignore import * as ReactClient from '@vitejs/plugin-rsc/vendor/react-server-dom/client.browser' -import type { CallServerCallback } from '../types' +import type { + CallServerCallback, + CreateFromReadableStreamCsrOptions, + EncodeReplyOptions, +} from '../types' export { setRequireModule } from '../core/browser' export function createFromReadableStream( stream: ReadableStream, - options: object = {}, + options: CreateFromReadableStreamCsrOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { callServer, @@ -17,7 +21,7 @@ export function createFromReadableStream( export function createFromFetch( promiseForResponse: Promise, - options: object = {}, + options: CreateFromReadableStreamCsrOptions = {}, ): Promise { return ReactClient.createFromFetch(promiseForResponse, { callServer, @@ -28,7 +32,7 @@ export function createFromFetch( export const encodeReply: ( v: unknown[], - options?: unknown, + options?: EncodeReplyOptions, ) => Promise = ReactClient.encodeReply export const createServerReference: (...args: any[]) => unknown = diff --git a/packages/plugin-rsc/src/react/rsc.ts b/packages/plugin-rsc/src/react/rsc.ts index 1eecfc5ef..3b05809f9 100644 --- a/packages/plugin-rsc/src/react/rsc.ts +++ b/packages/plugin-rsc/src/react/rsc.ts @@ -8,12 +8,18 @@ import { createServerDecodeClientManifest, createServerManifest, } from '../core/rsc' +import type { + CreateFromReadableStreamSsrOptions, + DecodeReplyOptions, + EncodeReplyOptions, + RenderToReadableStreamOptions, +} from '../types' export { loadServerAction, setRequireModule } from '../core/rsc' export function renderToReadableStream( data: T, - options?: object, + options?: RenderToReadableStreamOptions, extraOptions?: { /** * @internal @@ -32,7 +38,7 @@ export function renderToReadableStream( export function createFromReadableStream( stream: ReadableStream, - options: object = {}, + options: CreateFromReadableStreamSsrOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { serverConsumerManifest: { @@ -61,7 +67,7 @@ export const registerServerReference: ( export function decodeReply( body: string | FormData, - options?: unknown, + options?: DecodeReplyOptions, ): Promise { return ReactServer.decodeReply(body, createServerManifest(), options) } @@ -82,7 +88,7 @@ export const createTemporaryReferenceSet: () => unknown = export const encodeReply: ( v: unknown[], - options?: unknown, + options?: EncodeReplyOptions, ) => Promise = ReactClient.encodeReply export const createClientTemporaryReferenceSet: () => unknown = diff --git a/packages/plugin-rsc/src/react/ssr.ts b/packages/plugin-rsc/src/react/ssr.ts index caa325750..8c8edac41 100644 --- a/packages/plugin-rsc/src/react/ssr.ts +++ b/packages/plugin-rsc/src/react/ssr.ts @@ -1,12 +1,13 @@ // @ts-ignore import * as ReactClient from '@vitejs/plugin-rsc/vendor/react-server-dom/client.edge' import { createServerConsumerManifest } from '../core/ssr' +import type { CreateFromReadableStreamSsrOptions } from '../types' export { setRequireModule } from '../core/ssr' export function createFromReadableStream( stream: ReadableStream, - options: object = {}, + options: CreateFromReadableStreamSsrOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { serverConsumerManifest: createServerConsumerManifest(), diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index aae722125..08320f7ca 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -25,3 +25,44 @@ export interface ServerConsumerManifest { } export type CallServerCallback = (id: string, args: unknown[]) => unknown + +// Best-effort latest RSC API types based on react-server-dom-webpack +// https://github.com/wakujs/waku/blob/2ce74ee2381f6c0593b8246f33043434706889fe/packages/waku/src/lib/react-types.d.ts + +export type ServerTemporaryReferenceSet = WeakMap +export type ClientTemporaryReferenceSet = Map + +// react-server-dom/server.edge + +export interface RenderToReadableStreamOptions { + debugChannel?: { readable?: ReadableStream; writable?: WritableStream } + environmentName?: string + identifierPrefix?: string + signal?: AbortSignal + temporaryReferences?: ServerTemporaryReferenceSet + onError?: (error: unknown) => void + onPostpone?: (reason: string) => void +} + +export interface DecodeReplyOptions { + temporaryReferences?: ServerTemporaryReferenceSet +} + +// react-server-dom/client (browser) + +export interface CreateFromReadableStreamCsrOptions { + callServer?: CallServerCallback + debugChannel?: { writable?: WritableStream; readable?: ReadableStream } + findSourceMapURL?: (filename: string, environmentName: string) => string + temporaryReferences?: ClientTemporaryReferenceSet +} + +export interface EncodeReplyOptions { + temporaryReferences?: ClientTemporaryReferenceSet +} + +// react-server-dom/client.edge + +export interface CreateFromReadableStreamSsrOptions { + nonce?: string +} From e66f558067f485180d296e510cfa7890780f061a Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:01:43 +0900 Subject: [PATCH 02/14] chore: move --- packages/plugin-rsc/src/types/index.ts | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 08320f7ca..8d2c16ee2 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -29,11 +29,6 @@ export type CallServerCallback = (id: string, args: unknown[]) => unknown // Best-effort latest RSC API types based on react-server-dom-webpack // https://github.com/wakujs/waku/blob/2ce74ee2381f6c0593b8246f33043434706889fe/packages/waku/src/lib/react-types.d.ts -export type ServerTemporaryReferenceSet = WeakMap -export type ClientTemporaryReferenceSet = Map - -// react-server-dom/server.edge - export interface RenderToReadableStreamOptions { debugChannel?: { readable?: ReadableStream; writable?: WritableStream } environmentName?: string @@ -44,12 +39,6 @@ export interface RenderToReadableStreamOptions { onPostpone?: (reason: string) => void } -export interface DecodeReplyOptions { - temporaryReferences?: ServerTemporaryReferenceSet -} - -// react-server-dom/client (browser) - export interface CreateFromReadableStreamCsrOptions { callServer?: CallServerCallback debugChannel?: { writable?: WritableStream; readable?: ReadableStream } @@ -57,12 +46,17 @@ export interface CreateFromReadableStreamCsrOptions { temporaryReferences?: ClientTemporaryReferenceSet } -export interface EncodeReplyOptions { - temporaryReferences?: ClientTemporaryReferenceSet +export interface CreateFromReadableStreamSsrOptions { + nonce?: string } -// react-server-dom/client.edge +export interface DecodeReplyOptions { + temporaryReferences?: ServerTemporaryReferenceSet +} -export interface CreateFromReadableStreamSsrOptions { - nonce?: string +export interface EncodeReplyOptions { + temporaryReferences?: ClientTemporaryReferenceSet } + +export type ServerTemporaryReferenceSet = WeakMap +export type ClientTemporaryReferenceSet = Map From 3ec6ea9d9ac296d32883742b1853b976b61767b5 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:02:30 +0900 Subject: [PATCH 03/14] chore: cleanup --- packages/plugin-rsc/src/types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 8d2c16ee2..66f046f14 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -26,7 +26,7 @@ export interface ServerConsumerManifest { export type CallServerCallback = (id: string, args: unknown[]) => unknown -// Best-effort latest RSC API types based on react-server-dom-webpack +// Best-effort latest RSC API types // https://github.com/wakujs/waku/blob/2ce74ee2381f6c0593b8246f33043434706889fe/packages/waku/src/lib/react-types.d.ts export interface RenderToReadableStreamOptions { From 51f3adae3a17884089683641c37ba63920f616c8 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:11:47 +0900 Subject: [PATCH 04/14] chore: fixup --- .../react-router/react-router-vite/entry.rsc.tsx | 2 +- .../starter-cf-single/src/framework/entry.rsc.tsx | 4 +++- .../examples/starter/src/framework/entry.rsc.tsx | 4 +++- packages/plugin-rsc/src/react/browser.ts | 9 +++++---- packages/plugin-rsc/src/react/rsc.ts | 10 ++++++---- packages/plugin-rsc/src/react/ssr.ts | 4 ++-- packages/plugin-rsc/src/types/index.ts | 14 ++++++++++---- 7 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx index 847211bfd..5d085c2be 100644 --- a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx @@ -15,7 +15,7 @@ export function fetchServer(request: Request) { createTemporaryReferenceSet, decodeAction, decodeFormState, - decodeReply, + decodeReply: decodeReply as any, loadServerAction, // The incoming request. request, diff --git a/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx b/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx index 7516512d3..8f2e0c92e 100644 --- a/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx @@ -24,7 +24,9 @@ async function handler(request: Request): Promise { // handle server function request let returnValue: RscPayload['returnValue'] | undefined let formState: ReactFormState | undefined - let temporaryReferences: unknown | undefined + let temporaryReferences: + | ReturnType + | undefined let actionStatus: number | undefined if (renderRequest.isAction === true) { if (renderRequest.actionId) { diff --git a/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx b/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx index c9cf5c4b3..15bac7e6a 100644 --- a/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx @@ -35,7 +35,9 @@ async function handler(request: Request): Promise { // handle server function request let returnValue: RscPayload['returnValue'] | undefined let formState: ReactFormState | undefined - let temporaryReferences: unknown | undefined + let temporaryReferences: + | ReturnType + | undefined let actionStatus: number | undefined if (renderRequest.isAction === true) { if (renderRequest.actionId) { diff --git a/packages/plugin-rsc/src/react/browser.ts b/packages/plugin-rsc/src/react/browser.ts index 880ffcfcc..fc1577596 100644 --- a/packages/plugin-rsc/src/react/browser.ts +++ b/packages/plugin-rsc/src/react/browser.ts @@ -2,7 +2,8 @@ import * as ReactClient from '@vitejs/plugin-rsc/vendor/react-server-dom/client.browser' import type { CallServerCallback, - CreateFromReadableStreamCsrOptions, + ClientTemporaryReferenceSet, + CreateFromReadableStreamBrowserOptions, EncodeReplyOptions, } from '../types' @@ -10,7 +11,7 @@ export { setRequireModule } from '../core/browser' export function createFromReadableStream( stream: ReadableStream, - options: CreateFromReadableStreamCsrOptions = {}, + options: CreateFromReadableStreamBrowserOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { callServer, @@ -21,7 +22,7 @@ export function createFromReadableStream( export function createFromFetch( promiseForResponse: Promise, - options: CreateFromReadableStreamCsrOptions = {}, + options: CreateFromReadableStreamBrowserOptions = {}, ): Promise { return ReactClient.createFromFetch(promiseForResponse, { callServer, @@ -51,7 +52,7 @@ export function setServerCallback(fn: CallServerCallback): void { export type { CallServerCallback } -export const createTemporaryReferenceSet: () => unknown = +export const createTemporaryReferenceSet: () => ClientTemporaryReferenceSet = ReactClient.createTemporaryReferenceSet export function findSourceMapURL( diff --git a/packages/plugin-rsc/src/react/rsc.ts b/packages/plugin-rsc/src/react/rsc.ts index 3b05809f9..149ddcfe8 100644 --- a/packages/plugin-rsc/src/react/rsc.ts +++ b/packages/plugin-rsc/src/react/rsc.ts @@ -9,10 +9,12 @@ import { createServerManifest, } from '../core/rsc' import type { - CreateFromReadableStreamSsrOptions, + ClientTemporaryReferenceSet, + CreateFromReadableStreamEdgeOptions, DecodeReplyOptions, EncodeReplyOptions, RenderToReadableStreamOptions, + ServerTemporaryReferenceSet, } from '../types' export { loadServerAction, setRequireModule } from '../core/rsc' @@ -38,7 +40,7 @@ export function renderToReadableStream( export function createFromReadableStream( stream: ReadableStream, - options: CreateFromReadableStreamSsrOptions = {}, + options: CreateFromReadableStreamEdgeOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { serverConsumerManifest: { @@ -83,7 +85,7 @@ export function decodeFormState( return ReactServer.decodeFormState(actionResult, body, createServerManifest()) } -export const createTemporaryReferenceSet: () => unknown = +export const createTemporaryReferenceSet: () => ServerTemporaryReferenceSet = ReactServer.createTemporaryReferenceSet export const encodeReply: ( @@ -91,5 +93,5 @@ export const encodeReply: ( options?: EncodeReplyOptions, ) => Promise = ReactClient.encodeReply -export const createClientTemporaryReferenceSet: () => unknown = +export const createClientTemporaryReferenceSet: () => ClientTemporaryReferenceSet = ReactClient.createTemporaryReferenceSet diff --git a/packages/plugin-rsc/src/react/ssr.ts b/packages/plugin-rsc/src/react/ssr.ts index 8c8edac41..906ed3aac 100644 --- a/packages/plugin-rsc/src/react/ssr.ts +++ b/packages/plugin-rsc/src/react/ssr.ts @@ -1,13 +1,13 @@ // @ts-ignore import * as ReactClient from '@vitejs/plugin-rsc/vendor/react-server-dom/client.edge' import { createServerConsumerManifest } from '../core/ssr' -import type { CreateFromReadableStreamSsrOptions } from '../types' +import type { CreateFromReadableStreamEdgeOptions } from '../types' export { setRequireModule } from '../core/ssr' export function createFromReadableStream( stream: ReadableStream, - options: CreateFromReadableStreamSsrOptions = {}, + options: CreateFromReadableStreamEdgeOptions = {}, ): Promise { return ReactClient.createFromReadableStream(stream, { serverConsumerManifest: createServerConsumerManifest(), diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 66f046f14..fd94859e7 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -39,15 +39,18 @@ export interface RenderToReadableStreamOptions { onPostpone?: (reason: string) => void } -export interface CreateFromReadableStreamCsrOptions { +export interface CreateFromReadableStreamBrowserOptions { callServer?: CallServerCallback debugChannel?: { writable?: WritableStream; readable?: ReadableStream } findSourceMapURL?: (filename: string, environmentName: string) => string temporaryReferences?: ClientTemporaryReferenceSet } -export interface CreateFromReadableStreamSsrOptions { +export interface CreateFromReadableStreamEdgeOptions { nonce?: string + environmentName?: string + replayConsoleLogs?: boolean + temporaryReferences?: ClientTemporaryReferenceSet } export interface DecodeReplyOptions { @@ -58,5 +61,8 @@ export interface EncodeReplyOptions { temporaryReferences?: ClientTemporaryReferenceSet } -export type ServerTemporaryReferenceSet = WeakMap -export type ClientTemporaryReferenceSet = Map +// TODO: for now keep them unknown +// export type ServerTemporaryReferenceSet = WeakMap +// export type ClientTemporaryReferenceSet = Map +export type ServerTemporaryReferenceSet = unknown +export type ClientTemporaryReferenceSet = unknown From 024bf4dd4cb9979cfd4fa8d27d55000fd534527b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:13:12 +0900 Subject: [PATCH 05/14] chore: cleanup --- packages/plugin-rsc/src/types/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index fd94859e7..f56db50aa 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -40,9 +40,7 @@ export interface RenderToReadableStreamOptions { } export interface CreateFromReadableStreamBrowserOptions { - callServer?: CallServerCallback debugChannel?: { writable?: WritableStream; readable?: ReadableStream } - findSourceMapURL?: (filename: string, environmentName: string) => string temporaryReferences?: ClientTemporaryReferenceSet } From 9446aa075b79c737f6ceda4835db2bad715211e6 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:18:39 +0900 Subject: [PATCH 06/14] chore: more types --- packages/plugin-rsc/src/types/index.ts | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index f56db50aa..88d462bdb 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -29,34 +29,52 @@ export type CallServerCallback = (id: string, args: unknown[]) => unknown // Best-effort latest RSC API types // https://github.com/wakujs/waku/blob/2ce74ee2381f6c0593b8246f33043434706889fe/packages/waku/src/lib/react-types.d.ts +// https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js#L64-L73 export interface RenderToReadableStreamOptions { debugChannel?: { readable?: ReadableStream; writable?: WritableStream } - environmentName?: string + environmentName?: string | (() => string) + filterStackFrame?: (url: string, functionName: string) => boolean identifierPrefix?: string signal?: AbortSignal + startTime?: number temporaryReferences?: ServerTemporaryReferenceSet onError?: (error: unknown) => void - onPostpone?: (reason: string) => void } +// https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js#L47-L57 export interface CreateFromReadableStreamBrowserOptions { + callServer?: CallServerCallback debugChannel?: { writable?: WritableStream; readable?: ReadableStream } + endTime?: number + environmentName?: string + findSourceMapURL?: (filename: string, environmentName: string) => string + replayConsoleLogs?: boolean + startTime?: number temporaryReferences?: ClientTemporaryReferenceSet } +// https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js#L74-L87 export interface CreateFromReadableStreamEdgeOptions { - nonce?: string + debugChannel?: { readable?: ReadableStream } + endTime?: number environmentName?: string + findSourceMapURL?: (filename: string, environmentName: string) => string + nonce?: string replayConsoleLogs?: boolean + startTime?: number temporaryReferences?: ClientTemporaryReferenceSet } +// https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js#L247-L253 export interface DecodeReplyOptions { temporaryReferences?: ServerTemporaryReferenceSet + arraySizeLimit?: number } +// https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js#L261-L263 export interface EncodeReplyOptions { temporaryReferences?: ClientTemporaryReferenceSet + signal?: AbortSignal } // TODO: for now keep them unknown From d4cb6a1146a87a36e74fecea715cdd7a6af706a9 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:19:52 +0900 Subject: [PATCH 07/14] chore: strip overwritten ones --- packages/plugin-rsc/src/types/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 88d462bdb..418f34443 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -43,11 +43,9 @@ export interface RenderToReadableStreamOptions { // https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js#L47-L57 export interface CreateFromReadableStreamBrowserOptions { - callServer?: CallServerCallback debugChannel?: { writable?: WritableStream; readable?: ReadableStream } endTime?: number environmentName?: string - findSourceMapURL?: (filename: string, environmentName: string) => string replayConsoleLogs?: boolean startTime?: number temporaryReferences?: ClientTemporaryReferenceSet @@ -58,7 +56,6 @@ export interface CreateFromReadableStreamEdgeOptions { debugChannel?: { readable?: ReadableStream } endTime?: number environmentName?: string - findSourceMapURL?: (filename: string, environmentName: string) => string nonce?: string replayConsoleLogs?: boolean startTime?: number From 676e12c8e98c6f75a0990e58db9370045ffd6ac8 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:20:36 +0900 Subject: [PATCH 08/14] chore: revert examples --- .../examples/react-router/react-router-vite/entry.rsc.tsx | 2 +- .../examples/starter-cf-single/src/framework/entry.rsc.tsx | 4 +--- .../plugin-rsc/examples/starter/src/framework/entry.rsc.tsx | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx index 5d085c2be..847211bfd 100644 --- a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx @@ -15,7 +15,7 @@ export function fetchServer(request: Request) { createTemporaryReferenceSet, decodeAction, decodeFormState, - decodeReply: decodeReply as any, + decodeReply, loadServerAction, // The incoming request. request, diff --git a/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx b/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx index 8f2e0c92e..7516512d3 100644 --- a/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/starter-cf-single/src/framework/entry.rsc.tsx @@ -24,9 +24,7 @@ async function handler(request: Request): Promise { // handle server function request let returnValue: RscPayload['returnValue'] | undefined let formState: ReactFormState | undefined - let temporaryReferences: - | ReturnType - | undefined + let temporaryReferences: unknown | undefined let actionStatus: number | undefined if (renderRequest.isAction === true) { if (renderRequest.actionId) { diff --git a/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx b/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx index 15bac7e6a..c9cf5c4b3 100644 --- a/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/starter/src/framework/entry.rsc.tsx @@ -35,9 +35,7 @@ async function handler(request: Request): Promise { // handle server function request let returnValue: RscPayload['returnValue'] | undefined let formState: ReactFormState | undefined - let temporaryReferences: - | ReturnType - | undefined + let temporaryReferences: unknown | undefined let actionStatus: number | undefined if (renderRequest.isAction === true) { if (renderRequest.actionId) { From c5b9167af55b2cfba92b5701395c272adf1c1003 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:27:05 +0900 Subject: [PATCH 09/14] fix: XxxStream --- packages/plugin-rsc/src/types/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 418f34443..25c66d2e1 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -31,7 +31,7 @@ export type CallServerCallback = (id: string, args: unknown[]) => unknown // https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js#L64-L73 export interface RenderToReadableStreamOptions { - debugChannel?: { readable?: ReadableStream; writable?: WritableStream } + debugChannel?: DebugChannel environmentName?: string | (() => string) filterStackFrame?: (url: string, functionName: string) => boolean identifierPrefix?: string @@ -43,7 +43,7 @@ export interface RenderToReadableStreamOptions { // https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js#L47-L57 export interface CreateFromReadableStreamBrowserOptions { - debugChannel?: { writable?: WritableStream; readable?: ReadableStream } + debugChannel?: DebugChannel endTime?: number environmentName?: string replayConsoleLogs?: boolean @@ -53,7 +53,7 @@ export interface CreateFromReadableStreamBrowserOptions { // https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js#L74-L87 export interface CreateFromReadableStreamEdgeOptions { - debugChannel?: { readable?: ReadableStream } + debugChannel?: DebugChannel endTime?: number environmentName?: string nonce?: string @@ -74,6 +74,11 @@ export interface EncodeReplyOptions { signal?: AbortSignal } +type DebugChannel = { + readable?: ReadableStream + writable?: WritableStream +} + // TODO: for now keep them unknown // export type ServerTemporaryReferenceSet = WeakMap // export type ClientTemporaryReferenceSet = Map From 65b4350df4662d1d3effa979d5fe0dfe918d0ac8 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:28:13 +0900 Subject: [PATCH 10/14] fix: allow callServer override --- packages/plugin-rsc/src/types/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 25c66d2e1..1a43c338a 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -43,6 +43,7 @@ export interface RenderToReadableStreamOptions { // https://github.com/facebook/react/blob/8b2e903a7447d370eb77bb117bc4c0ae240ce831/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js#L47-L57 export interface CreateFromReadableStreamBrowserOptions { + callServer?: CallServerCallback debugChannel?: DebugChannel endTime?: number environmentName?: string From 191c379e480cafebf2a5bcc90b1fefe493352379 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:33:08 +0900 Subject: [PATCH 11/14] fix: tweak reply types --- .../examples/basic/src/framework/use-cache-runtime.tsx | 2 +- packages/plugin-rsc/src/react/browser.ts | 2 +- packages/plugin-rsc/src/react/rsc.ts | 4 ++-- packages/plugin-rsc/src/types/index.ts | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx b/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx index a25e56c6c..e33705573 100644 --- a/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx +++ b/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx @@ -50,7 +50,7 @@ export default function cacheWrapper(fn: (...args: any[]) => Promise) { }) // run the original function - const result = await fn(...decodedArgs) + const result = await fn(...(decodedArgs as any[])) // serialize result to a ReadableStream const stream = renderToReadableStream(result, { diff --git a/packages/plugin-rsc/src/react/browser.ts b/packages/plugin-rsc/src/react/browser.ts index fc1577596..00b6cacc5 100644 --- a/packages/plugin-rsc/src/react/browser.ts +++ b/packages/plugin-rsc/src/react/browser.ts @@ -32,7 +32,7 @@ export function createFromFetch( } export const encodeReply: ( - v: unknown[], + v: unknown, options?: EncodeReplyOptions, ) => Promise = ReactClient.encodeReply diff --git a/packages/plugin-rsc/src/react/rsc.ts b/packages/plugin-rsc/src/react/rsc.ts index 149ddcfe8..6db6735c8 100644 --- a/packages/plugin-rsc/src/react/rsc.ts +++ b/packages/plugin-rsc/src/react/rsc.ts @@ -70,7 +70,7 @@ export const registerServerReference: ( export function decodeReply( body: string | FormData, options?: DecodeReplyOptions, -): Promise { +): Promise { return ReactServer.decodeReply(body, createServerManifest(), options) } @@ -89,7 +89,7 @@ export const createTemporaryReferenceSet: () => ServerTemporaryReferenceSet = ReactServer.createTemporaryReferenceSet export const encodeReply: ( - v: unknown[], + v: unknown, options?: EncodeReplyOptions, ) => Promise = ReactClient.encodeReply diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 1a43c338a..89a0eb7e9 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -24,7 +24,10 @@ export interface ServerConsumerManifest { } } -export type CallServerCallback = (id: string, args: unknown[]) => unknown +export type CallServerCallback = ( + id: string, + args: unknown[], +) => Promise // Best-effort latest RSC API types // https://github.com/wakujs/waku/blob/2ce74ee2381f6c0593b8246f33043434706889fe/packages/waku/src/lib/react-types.d.ts From 644a7ca9930a9a222293384be0a0d08f722514f3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:39:19 +0900 Subject: [PATCH 12/14] chore: fix react-router types --- .../examples/react-router/react-router-vite/entry.rsc.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx index 847211bfd..5d085c2be 100644 --- a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx @@ -15,7 +15,7 @@ export function fetchServer(request: Request) { createTemporaryReferenceSet, decodeAction, decodeFormState, - decodeReply, + decodeReply: decodeReply as any, loadServerAction, // The incoming request. request, From a1f45ca1d12c07b380e3f376a95cce32a004a9c3 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:48:57 +0900 Subject: [PATCH 13/14] fix: loosen up for now --- packages/plugin-rsc/src/react/browser.ts | 7 ++----- packages/plugin-rsc/src/react/rsc.ts | 17 +++++------------ packages/plugin-rsc/src/types/index.ts | 10 ++++++++++ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/plugin-rsc/src/react/browser.ts b/packages/plugin-rsc/src/react/browser.ts index 00b6cacc5..60c2d96ca 100644 --- a/packages/plugin-rsc/src/react/browser.ts +++ b/packages/plugin-rsc/src/react/browser.ts @@ -4,7 +4,7 @@ import type { CallServerCallback, ClientTemporaryReferenceSet, CreateFromReadableStreamBrowserOptions, - EncodeReplyOptions, + EncodeReplyFunction, } from '../types' export { setRequireModule } from '../core/browser' @@ -31,10 +31,7 @@ export function createFromFetch( }) } -export const encodeReply: ( - v: unknown, - options?: EncodeReplyOptions, -) => Promise = ReactClient.encodeReply +export const encodeReply: EncodeReplyFunction = ReactClient.encodeReply export const createServerReference: (...args: any[]) => unknown = ReactClient.createServerReference diff --git a/packages/plugin-rsc/src/react/rsc.ts b/packages/plugin-rsc/src/react/rsc.ts index 6db6735c8..117fe15ec 100644 --- a/packages/plugin-rsc/src/react/rsc.ts +++ b/packages/plugin-rsc/src/react/rsc.ts @@ -11,8 +11,8 @@ import { import type { ClientTemporaryReferenceSet, CreateFromReadableStreamEdgeOptions, - DecodeReplyOptions, - EncodeReplyOptions, + DecodeReplyFunction, + EncodeReplyFunction, RenderToReadableStreamOptions, ServerTemporaryReferenceSet, } from '../types' @@ -67,12 +67,8 @@ export const registerServerReference: ( name: string, ) => T = ReactServer.registerServerReference -export function decodeReply( - body: string | FormData, - options?: DecodeReplyOptions, -): Promise { - return ReactServer.decodeReply(body, createServerManifest(), options) -} +export const decodeReply: DecodeReplyFunction = (body, options) => + ReactServer.decodeReply(body, createServerManifest(), options) export function decodeAction(body: FormData): Promise<() => Promise> { return ReactServer.decodeAction(body, createServerManifest()) @@ -88,10 +84,7 @@ export function decodeFormState( export const createTemporaryReferenceSet: () => ServerTemporaryReferenceSet = ReactServer.createTemporaryReferenceSet -export const encodeReply: ( - v: unknown, - options?: EncodeReplyOptions, -) => Promise = ReactClient.encodeReply +export const encodeReply: EncodeReplyFunction = ReactClient.encodeReply export const createClientTemporaryReferenceSet: () => ClientTemporaryReferenceSet = ReactClient.createTemporaryReferenceSet diff --git a/packages/plugin-rsc/src/types/index.ts b/packages/plugin-rsc/src/types/index.ts index 89a0eb7e9..bb827a7b4 100644 --- a/packages/plugin-rsc/src/types/index.ts +++ b/packages/plugin-rsc/src/types/index.ts @@ -78,6 +78,16 @@ export interface EncodeReplyOptions { signal?: AbortSignal } +// TODO: technically encode/decodeReply can serialize non-array values +export type EncodeReplyFunction = ( + value: unknown[], + options?: EncodeReplyOptions, +) => Promise +export type DecodeReplyFunction = ( + body: string | FormData, + options?: DecodeReplyOptions, +) => Promise + type DebugChannel = { readable?: ReadableStream writable?: WritableStream From 0b53907013a0e58d19c8c157542a84b7c12f3c60 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Sat, 21 Mar 2026 17:49:28 +0900 Subject: [PATCH 14/14] chore: revert back example --- .../examples/basic/src/framework/use-cache-runtime.tsx | 2 +- .../examples/react-router/react-router-vite/entry.rsc.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx b/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx index e33705573..a25e56c6c 100644 --- a/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx +++ b/packages/plugin-rsc/examples/basic/src/framework/use-cache-runtime.tsx @@ -50,7 +50,7 @@ export default function cacheWrapper(fn: (...args: any[]) => Promise) { }) // run the original function - const result = await fn(...(decodedArgs as any[])) + const result = await fn(...decodedArgs) // serialize result to a ReadableStream const stream = renderToReadableStream(result, { diff --git a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx index 5d085c2be..847211bfd 100644 --- a/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx +++ b/packages/plugin-rsc/examples/react-router/react-router-vite/entry.rsc.tsx @@ -15,7 +15,7 @@ export function fetchServer(request: Request) { createTemporaryReferenceSet, decodeAction, decodeFormState, - decodeReply: decodeReply as any, + decodeReply, loadServerAction, // The incoming request. request,