Skip to content
18 changes: 10 additions & 8 deletions packages/plugin-rsc/src/react/browser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// @ts-ignore
import * as ReactClient from '@vitejs/plugin-rsc/vendor/react-server-dom/client.browser'
import type { CallServerCallback } from '../types'
import type {
CallServerCallback,
ClientTemporaryReferenceSet,
CreateFromReadableStreamBrowserOptions,
EncodeReplyFunction,
} from '../types'

export { setRequireModule } from '../core/browser'

export function createFromReadableStream<T>(
stream: ReadableStream<Uint8Array>,
options: object = {},
options: CreateFromReadableStreamBrowserOptions = {},
): Promise<T> {
return ReactClient.createFromReadableStream(stream, {
callServer,
Expand All @@ -17,7 +22,7 @@ export function createFromReadableStream<T>(

export function createFromFetch<T>(
promiseForResponse: Promise<Response>,
options: object = {},
options: CreateFromReadableStreamBrowserOptions = {},
): Promise<T> {
return ReactClient.createFromFetch(promiseForResponse, {
callServer,
Expand All @@ -26,10 +31,7 @@ export function createFromFetch<T>(
})
}

export const encodeReply: (
v: unknown[],
options?: unknown,
) => Promise<string | FormData> = ReactClient.encodeReply
export const encodeReply: EncodeReplyFunction = ReactClient.encodeReply

export const createServerReference: (...args: any[]) => unknown =
ReactClient.createServerReference
Expand All @@ -47,7 +49,7 @@ export function setServerCallback(fn: CallServerCallback): void {

export type { CallServerCallback }

export const createTemporaryReferenceSet: () => unknown =
export const createTemporaryReferenceSet: () => ClientTemporaryReferenceSet =
ReactClient.createTemporaryReferenceSet

export function findSourceMapURL(
Expand Down
29 changes: 15 additions & 14 deletions packages/plugin-rsc/src/react/rsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@ import {
createServerDecodeClientManifest,
createServerManifest,
} from '../core/rsc'
import type {
ClientTemporaryReferenceSet,
CreateFromReadableStreamEdgeOptions,
DecodeReplyFunction,
EncodeReplyFunction,
RenderToReadableStreamOptions,
ServerTemporaryReferenceSet,
} from '../types'

export { loadServerAction, setRequireModule } from '../core/rsc'

export function renderToReadableStream<T>(
data: T,
options?: object,
options?: RenderToReadableStreamOptions,
extraOptions?: {
/**
* @internal
Expand All @@ -32,7 +40,7 @@ export function renderToReadableStream<T>(

export function createFromReadableStream<T>(
stream: ReadableStream<Uint8Array>,
options: object = {},
options: CreateFromReadableStreamEdgeOptions = {},
): Promise<T> {
return ReactClient.createFromReadableStream(stream, {
serverConsumerManifest: {
Expand All @@ -59,12 +67,8 @@ export const registerServerReference: <T>(
name: string,
) => T = ReactServer.registerServerReference

export function decodeReply(
body: string | FormData,
options?: unknown,
): Promise<unknown[]> {
return ReactServer.decodeReply(body, createServerManifest(), options)
}
export const decodeReply: DecodeReplyFunction = (body, options) =>
ReactServer.decodeReply(body, createServerManifest(), options)

export function decodeAction(body: FormData): Promise<() => Promise<void>> {
return ReactServer.decodeAction(body, createServerManifest())
Expand All @@ -77,13 +81,10 @@ export function decodeFormState(
return ReactServer.decodeFormState(actionResult, body, createServerManifest())
}

export const createTemporaryReferenceSet: () => unknown =
export const createTemporaryReferenceSet: () => ServerTemporaryReferenceSet =
ReactServer.createTemporaryReferenceSet

export const encodeReply: (
v: unknown[],
options?: unknown,
) => Promise<string | FormData> = ReactClient.encodeReply
export const encodeReply: EncodeReplyFunction = ReactClient.encodeReply

export const createClientTemporaryReferenceSet: () => unknown =
export const createClientTemporaryReferenceSet: () => ClientTemporaryReferenceSet =
ReactClient.createTemporaryReferenceSet
3 changes: 2 additions & 1 deletion packages/plugin-rsc/src/react/ssr.ts
Original file line number Diff line number Diff line change
@@ -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 { CreateFromReadableStreamEdgeOptions } from '../types'

export { setRequireModule } from '../core/ssr'

export function createFromReadableStream<T>(
stream: ReadableStream<Uint8Array>,
options: object = {},
options: CreateFromReadableStreamEdgeOptions = {},
): Promise<T> {
return ReactClient.createFromReadableStream(stream, {
serverConsumerManifest: createServerConsumerManifest(),
Expand Down
75 changes: 74 additions & 1 deletion packages/plugin-rsc/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,77 @@ export interface ServerConsumerManifest {
}
}

export type CallServerCallback = (id: string, args: unknown[]) => unknown
export type CallServerCallback = (
id: string,
args: unknown[],
) => Promise<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?: DebugChannel
environmentName?: string | (() => string)
filterStackFrame?: (url: string, functionName: string) => boolean
identifierPrefix?: string
signal?: AbortSignal
startTime?: number
temporaryReferences?: ServerTemporaryReferenceSet
onError?: (error: unknown) => 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?: DebugChannel
endTime?: number
environmentName?: 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 {
debugChannel?: DebugChannel
endTime?: number
environmentName?: 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: technically encode/decodeReply can serialize non-array values
export type EncodeReplyFunction = (
value: unknown[],
options?: EncodeReplyOptions,
) => Promise<string | FormData>
export type DecodeReplyFunction = (
body: string | FormData,
options?: DecodeReplyOptions,
) => Promise<unknown[]>

type DebugChannel = {
readable?: ReadableStream<Uint8Array>
writable?: WritableStream<Uint8Array>
}

// TODO: for now keep them unknown
// export type ServerTemporaryReferenceSet = WeakMap<object, string>
// export type ClientTemporaryReferenceSet = Map<unknown, unknown>
export type ServerTemporaryReferenceSet = unknown
export type ClientTemporaryReferenceSet = unknown
Loading