Files
react/packages/react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js
Sebastian Markbåge 22b2b1a05a [Flight] Add serverModuleMap option for mapping ServerReferences (#31300)
Stacked on #31299.

We already have an option for resolving Client References to other
Client References when consuming an RSC payload on the server.

This lets you resolve Server References on the consuming side when the
environment where you're consuming the RSC payload also has access to
those Server References. Basically they becomes like Client References
for this consumer but for another consumer they wouldn't be.
2024-10-19 21:10:25 -04:00

106 lines
2.8 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {Thenable, ReactCustomFormAction} from 'shared/ReactTypes.js';
import type {
Response,
FindSourceMapURLCallback,
} from 'react-client/src/ReactFlightClient';
import type {
ServerConsumerModuleMap,
ModuleLoading,
ServerManifest,
} from 'react-client/src/ReactFlightClientConfig';
type ServerConsumerManifest = {
moduleMap: ServerConsumerModuleMap,
moduleLoading: ModuleLoading,
serverModuleMap: null | ServerManifest,
};
import type {Readable} from 'stream';
import {
createResponse,
getRoot,
reportGlobalError,
processStringChunk,
processBinaryChunk,
close,
} from 'react-client/src/ReactFlightClient';
import {createServerReference as createServerReferenceImpl} from 'react-client/src/ReactFlightReplyClient';
function noServerCall() {
throw new Error(
'Server Functions cannot be called during initial render. ' +
'This would create a fetch waterfall. Try to use a Server Component ' +
'to pass data to Client Components instead.',
);
}
export function createServerReference<A: Iterable<any>, T>(
id: any,
callServer: any,
): (...A) => Promise<T> {
return createServerReferenceImpl(id, noServerCall);
}
type EncodeFormActionCallback = <A>(
id: any,
args: Promise<A>,
) => ReactCustomFormAction;
export type Options = {
nonce?: string,
encodeFormAction?: EncodeFormActionCallback,
findSourceMapURL?: FindSourceMapURLCallback,
replayConsoleLogs?: boolean,
environmentName?: string,
};
function createFromNodeStream<T>(
stream: Readable,
serverConsumerManifest: ServerConsumerManifest,
options?: Options,
): Thenable<T> {
const response: Response = createResponse(
serverConsumerManifest.moduleMap,
serverConsumerManifest.serverModuleMap,
serverConsumerManifest.moduleLoading,
noServerCall,
options ? options.encodeFormAction : undefined,
options && typeof options.nonce === 'string' ? options.nonce : undefined,
undefined, // TODO: If encodeReply is supported, this should support temporaryReferences
__DEV__ && options && options.findSourceMapURL
? options.findSourceMapURL
: undefined,
__DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
__DEV__ && options && options.environmentName
? options.environmentName
: undefined,
);
stream.on('data', chunk => {
if (typeof chunk === 'string') {
processStringChunk(response, chunk);
} else {
processBinaryChunk(response, chunk);
}
});
stream.on('error', error => {
reportGlobalError(response, error);
});
stream.on('end', () => close(response));
return getRoot(response);
}
export {createFromNodeStream};