Files
Sebastian MarkbågeandGitHub 280ff6fed2 [Flight] Add Web Stream support to the Flight Client in Node (#33473)
This effectively lets us consume Web Streams in a Node build. In fact
the Node entry point is now just adding Node stream APIs.

For the client, this is simple because the configs are not actually
stream type specific. The server is a little trickier.
2025-06-06 17:14:15 -04:00

82 lines
2.3 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} from 'react-client/src/ReactFlightClient';
import type {Readable} from 'stream';
import {
createResponse,
getRoot,
reportGlobalError,
processBinaryChunk,
close,
} from 'react-client/src/ReactFlightClient';
export * from './ReactFlightDOMClientEdge';
function findSourceMapURL(filename: string, environmentName: string) {
const devServer = parcelRequire.meta.devServer;
if (devServer != null) {
const qs = new URLSearchParams();
qs.set('filename', filename);
qs.set('env', environmentName);
return devServer + '/__parcel_source_map?' + qs.toString();
}
return null;
}
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.',
);
}
type EncodeFormActionCallback = <A>(
id: any,
args: Promise<A>,
) => ReactCustomFormAction;
export type Options = {
nonce?: string,
encodeFormAction?: EncodeFormActionCallback,
replayConsoleLogs?: boolean,
environmentName?: string,
};
export function createFromNodeStream<T>(
stream: Readable,
options?: Options,
): Thenable<T> {
const response: Response = createResponse(
null, // bundlerConfig
null, // serverReferenceConfig
null, // 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__ ? findSourceMapURL : undefined,
__DEV__ && options ? options.replayConsoleLogs === true : false, // defaults to false
__DEV__ && options && options.environmentName
? options.environmentName
: undefined,
);
stream.on('data', chunk => {
processBinaryChunk(response, chunk);
});
stream.on('error', error => {
reportGlobalError(response, error);
});
stream.on('end', () => close(response));
return getRoot(response);
}